---
layout: api
page_title: PKI - Secrets Engines - HTTP API
description: This is the API documentation for the Vault PKI secrets engine.
---

# PKI secrets engine (API)

@include 'x509-sha1-deprecation.mdx'

This is the API documentation for the Vault PKI secrets engine. For general
information about the usage and operation of the PKI secrets engine, please see
the [PKI documentation](/vault/docs/secrets/pki).

This documentation assumes the PKI secrets engine is enabled at the `/pki` path
in Vault. Since it is possible to enable secrets engines at any location, please
update your API calls accordingly.

## Table of contents

- [Notice About New Multi-Issuer Functionality](#notice-about-new-multi-issuer-functionality)
- [ACME Certificate Issuance](#acme-certificate-issuance)
  - [ACME Directories](#acme-directories)
  - [Get ACME EAB Binding Token](#get-acme-eab-binding-token)
  - [List Unused ACME EAB Binding Tokens](#list-unused-acme-eab-binding-tokens)
  - [Delete Unused ACME EAB Binding Tokens](#delete-unused-acme-eab-binding-tokens)
  - [Get ACME Configuration](#get-acme-configuration)
  - [Set ACME Configuration](#set-acme-configuration)
- [Issuing Certificates](#issuing-certificates)
  - [List Roles](#list-roles)
  - [Read Role](#read-role)
  - [Generate Certificate and Key](#generate-certificate-and-key)
  - [Generate Certificate and Key with External Policy <EnterpriseAlert inline="true" />](#generate-certificate-and-key-with-external-policy)
  - [Sign Certificate](#sign-certificate)
  - [Sign Certificate with External Policy <EnterpriseAlert inline="true" />](#sign-certificate-with-external-policy)
  - [Sign Intermediate](#sign-intermediate)
  - [Sign Intermediate with External Policy <EnterpriseAlert inline="true" />](#sign-intermediate-with-external-policy)
  - [Sign Self-Issued](#sign-self-issued)
  - [Sign Verbatim](#sign-verbatim)
  - [Revoke Certificate](#revoke-certificate)
  - [Revoke Certificate with Private Key](#revoke-certificate-with-private-key)
  - [List Revoked Certificates](#list-revoked-certificates)
  - [List Revocation Requests](#list-revocation-requests)
  - [List Cross-Cluster Revocations](#list-cross-cluster-revocations)
- [Accessing Authority Information](#accessing-authority-information)
  - [List Issuers](#list-issuers)
  - [Read Issuer Certificate](#read-issuer-certificate)
  - [Read Default Issuer Certificate Chain](#read-default-issuer-certificate-chain)
  - [Read Issuer CRL](#read-issuer-crl)
  - [OCSP Request](#ocsp-request)
  - [List Certificates](#list-certificates)
  - [Read Certificate](#read-certificate)
- [Managing Keys and Issuers](#managing-keys-and-issuers)
  - [List Issuers](#list-issuers)
  - [List Keys](#list-keys)
  - [Generate Key](#generate-key)
  - [Generate Root](#generate-root)
  - [Generate Intermediate CSR](#generate-intermediate-csr)
  - [Import CA Certificates and Keys](#import-ca-certificates-and-keys)
  - [Read Issuer](#read-issuer)
  - [Update Issuer](#update-issuer)
  - [Revoke Issuer](#revoke-issuer)
  - [Delete Issuer](#delete-issuer)
  - [Import Key](#import-key)
  - [Read Key](#read-key)
  - [Update Key](#update-key)
  - [Delete Key](#delete-key)
  - [Delete All Issuers and Keys](#delete-all-issuers-and-keys)
- [Managing Authority Information](#managing-authority-information)
  - [List Roles](#list-roles)
  - [Create/Update Role](#create-update-role)
  - [Read Role](#read-role)
  - [Delete Role](#delete-role)
  - [Read Certificate Issuance External Policy Service (CIEPS) Configuration <EnterpriseAlert inline="true" />](#read-certificate-issuance-external-policy-service-cieps-configuration)
  - [Set Certificate Issuance External Policy Service (CIEPS) Configuration <EnterpriseAlert inline="true" />](#set-certificate-issuance-external-policy-service-cieps-configuration)
  - [Read URLs](#read-urls)
  - [Set URLs](#set-urls)
  - [Read Issuers Configuration](#read-issuers-configuration)
  - [Set Issuers Configuration](#set-issuers-configuration)
  - [Read Keys Configuration](#read-keys-configuration)
  - [Set Keys Configuration](#set-keys-configuration)
  - [Read Cluster Configuration](#read-cluster-configuration)
  - [Set Cluster Configuration](#set-cluster-configuration)
  - [Read CRL Configuration](#read-crl-configuration)
  - [Set CRL Configuration](#set-crl-configuration)
  - [Rotate CRLs](#rotate-crls)
  - [Rotate Delta CRLs](#rotate-delta-crls)
  - [Combining CRLs from the Same Issuer](#combine-crls-from-the-same-issuer)
  - [Sign Revocation List](#sign-revocation-list)
  - [Tidy](#tidy)
  - [Read Automatic Tidy Configuration](#read-automatic-tidy-configuration)
  - [Set Automatic Tidy Configuration](#set-automatic-tidy-configuration)
  - [Tidy Status](#tidy-status)
  - [Cancel Tidy](#cancel-tidy)
- [Cluster Scalability](#cluster-scalability)
- [Managed Key](#managed-keys) (Enterprise Only)
- [Vault CLI with DER/PEM responses](#vault-cli-with-der-pem-responses)

## Notice about new Multi-Issuer functionality

Vault since 1.11.0 allows a single PKI mount to have multiple Certificate
Authority (CA) certificates ("issuers") in a single mount, for the purpose
of facilitating rotation. All issuers within a single mount are treated as a
single Authority, meaning that:

 1. Certificate Revocation List (CRL) configuration is common to all issuers,
 2. All authority access URLs are common to all issuers,
 3. Issued certificates' serial numbers will be unique across all issuers.

However, since each issuer may have a distinct subject and keys, different
issuers may have different CRLs.

It is _strongly_ encouraged to limit the scope of CAs within a mount and not
to mix different types of CAs (roots and intermediates).

~> **Note**: Some functionality will not work if a default issuer is not
   configured. Vault automatically selects the default issuer from the
   current issuing certificate on migration from an older Vault version
   (Vault < 1.11.0).

## ACME certificate issuance

Starting with Vault 1.14, Vault supports the [ACME certificate lifecycle
management protocol](https://datatracker.ietf.org/doc/html/rfc8555) for issuing
and renewing leaf server certificates.

In order to use ACME, a [cluster path](#set-cluster-configuration) must be
set and ACME must be [enabled in its configuration](#set-acme-configuration)
with the [required headers](#acme-required-headers) enabled on the mount
tuning.

Using ACME with a role requires `no_store=false` to be set on the role; this
allows the certificate to be stored and later fetched through the ACME
protocol.

### ACME directories

Vault PKI supports the following ACME directories, providing different
restrictions around usage (defaults, a specific issuer and/or a specific
role). To interact with these directories, specify the directory URL in
an ACME client. For example, with the EFF's [CertBot](https://certbot.eff.org/):

```
$ certbot certonly --server https://localhost:8200/v1/pki/acme/directory ...
```

These endpoints are unauthenticated from a Vault authentication model, but
internally authenticated via the ACME protocol.

| Method | Path                                                               | Default Directory Policy   | Issuer                | Role          |
|:-------|:-------------------------------------------------------------------|:---------------------------|:----------------------|:--------------|
| `ACME` | `/pki/acme/directory`                                              | `sign-verbatim`            | `default`             | Sign-Verbatim |
| `ACME` | `/pki/acme/directory`                                              | `role:role_ref`            | Specified by the role | `:role_ref`   |
| `ACME` | `/pki/acme/directory`                                              | `external-policy(:policy)` | Specified by CIEPS    | CIEPS         |
| `ACME` | `/pki/issuer/:issuer_ref/acme/directory`                           | `sign-verbatim`            | `:issuer_ref`         | Sign-Verbatim |
| `ACME` | `/pki/issuer/:issuer_ref/acme/directory`                           | `role:role_ref`            | `:issuer_ref`         | `:role_ref`   |
| `ACME` | `/pki/roles/:role/acme/directory`                                  | (any)                      | Specified by the role | `:role`       |
| `ACME` | `/pki/issuer/:issuer_ref/roles/:role/acme/directory`               | (any)                      | `:issuer_ref`         | `:role`       |
| `ACME` | `/pki/external-policy(/:policy)/acme/directory`                    | (any)                      | Specified by CIEPS    | CIEPS         |
| `ACME` | `/pki/issuer/:issuer_ref/external-policy(/:policy)/acme/directory` | (any)                      | Specified by CIEPS    | CIEPS         |

When a role is not explicitly specified, behavior is specified by the
`default_directory_policy` in the [ACME configuration](#set-acme-configuration).
These directories can also be forbidden by setting that policy as `forbid`.  If
the policy is `sign-verbatim` then _any_ identifier for which the client can
prove ownership of will be issued for.  This is similar to using the
[Sign Verbatim](#sign-verbatim) endpoint, but with additional verification
that the client has proven ownership (within the ACME protocol) of the
requested certificate identifiers. When `external-policy` is specified as the
default value, the Certificate Issuance External
Policy Service (CIEPS)<EnterpriseAlert inline="true" /> is used for
validating and templating the certificate instead of a role; ACME's challenge
validation is still enforced. An optional policy name can be specified by using
`external-policy:policy`. Roles are not used when CIEPS is used.

#### ACME challenge types

Vault supports the following ACME challenge types presently:

 - `http-01`, supporting both `dns` and `ip` identifiers.
 - `dns-01`, supporting `dns` identifiers including wildcards.
 - `tls-alpn-01`, supporting only non-wildcard `dns` identifiers.

A custom DNS resolver used by the server for looking up DNS names for use
with both mechanisms can be added via the [ACME configuration](#set-acme-configuration).

#### ACME external account bindings

ACME External Account Binding (EAB) Policy can enforce that clients need to
have a valid external account binding to Vault. Before registering a new account,
an authenticated Vault client will need to [fetch a new EAB
token](#get-acme-eab-binding-token). This returns two values: a key identifier
and an HMAC key used by the ACME client to authenticate with EAB. For example:

```
$ vault write -f /pki/acme/new-eab
$ certbot certonly --server https://localhost:8200/v1/pki/acme/directory \
                   --eab-kid <id> --eab-hmac-key <hmac-key>
```

With or without EAB, requests from the ACME client are not authenticated using
traditional Vault authentication, but are instead authenticated through the
ACME protocol. With EAB however, a Vault authenticated client will have to
fetch an EAB token and pass it to the ACME client for use on the initial
registration: this binds the ACME client's registration to an authenticated
Vault endpoint, but not further to the client's entity or other information.

~> Note: Enabling EAB is strongly recommended for public-facing Vault
   deployments. Use of the `VAULT_DISABLE_PUBLIC_ACME` environment variable
   can be used to enforce all ACME instances have EAB enabled.

#### ACME accounts

ACME Accounts are created specific to a particular directory and are not
portable across Performance Secondary clusters.

#### ACME required headers

ACME requires the following response headers (`allowed_response_headers`)
to be specified by [mount tuning](/vault/api-docs/system/mounts#tune-mount-configuration):

 - `Replay-Nonce`
 - `Link`
 - `Location`

On an existing mount, these can be specified by running the following command:

```
$ vault secrets tune -allowed-response-headers=Location -allowed-response-headers=Replay-Nonce \
                     -allowed-response-headers=Link \
                     pki/
```

### Get ACME EAB binding token

This endpoint returns a new ACME binding token. The `id` response field can
be used as the key identifier and the `key` response field be used as the
EAB HMAC key in the ACME Client.

Each call to this endpoint will generate and return a new EAB binding token
that is linked to the specific ACME directory it resides under. EAB tokens
are not usable across different ACME directories.

| Method | Path                                               |
|:-------|:---------------------------------------------------|
| `POST` | `/pki/acme/new-eab`                                |
| `POST` | `/pki/issuer/:issuer_ref/acme/new-eab`             |
| `POST` | `/pki/roles/:role/acme/new-eab`                    |
| `POST` | `/pki/issuer/:issuer_ref/roles/:role/acme/new-eab` |

#### Parameters

No parameters.

#### Sample request

```
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    http://127.0.0.1:8200/v1/pki/acme/new-eab
```

#### Sample response

```
{
  "data": {
    "created_on": "2023-05-24T14:33:00-04:00",
    "id": "bc8088d9-3816-5177-ae8e-d8393265f7dd",
    "key_type": "hs",
    "acme_directory": "acme/directory",
    "key": "MHcCAQE... additional data elided ...",
  }
}
```

### List unused ACME EAB binding tokens

This endpoint returns a list of all unused ACME binding tokens; once used,
they will be removed from this list.

| Method | Path       |
| :----- | :--------- |
| `LIST` | `/pki/eab` |

#### Sample request

```
$ curl \
    --header "X-Vault-Token: ..." \
    --request LIST \
    http://127.0.0.1:8200/v1/pki/eab
```

#### Sample response

```
{
  "data": {
    "key_info": {
      "bc8088d9-3816-5177-ae8e-d8393265f7dd": {
        "created_on": "2023-05-24T14:33:00-04:00",
        "key_type": "hs",
        "acme_directory": "acme/directory"
      }
    },
    "keys": [
      "bc8088d9-3816-5177-ae8e-d8393265f7dd"
    ]
  }
}
```

### Delete unused ACME EAB binding tokens

This endpoint allows the deletion of an unused ACME binding token.

| Method   | Path               |
| :------- | :----------------- |
| `DELETE` | `/pki/eab/:key_id` |

#### Parameters

 - `key_id` `(string: <required>)` - The id of the EAB binding token to
   delete. This is part of the request URL.

#### Sample request

```
$ curl \
    --header "X-Vault-Token: ..." \
    --request DELETE \
    http://127.0.0.1:8200/v1/pki/eab/bc8088d9-3816-5177-ae8e-d8393265f7dd
```

### Get ACME configuration

This endpoint allows reading of the current ACME server configuration used by
this mount.

| Method | Path               |
| :----- | :----------------- |
| `GET`  | `/pki/config/acme` |

#### Sample request

```
$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/config/acme
```

#### Sample response

```
{
  "data": {
    "allowed_issuers": [
      "*"
    ],
    "allowed_roles": [
      "*"
    ],
    "default_directory_policy": "sign-verbatim",
    "dns_resolver": "",
    "eab_policy": "not-required",
    "enabled": true
  },
}
```

### Set ACME configuration

This endpoint allows setting the ACME server configuration used by this
mount.

| Method | Path               |
| :----- | :----------------- |
| `POST` | `/pki/config/acme` |

#### Parameters

 - `allowed_issuers` `(list: ["*"])` - Specifies a list issuers allowed to
   issue certificates via explicit ACME paths. If an allowed role specifies
   an issuer outside this list, it will be allowed. The default value `*`
   allows every issuer within the mount.

  - `allow_role_ext_key_usage` `(bool: false)` - whether the ExtKeyUsage field
   from a role is used, defaults to false meaning that certificate will be
   signed with ServerAuth.

 - `allowed_roles` `(list: ["*"])` - Specifies a list of roles allowed to
   issue certificates via explicit ACME paths.  The default value `*` allows
   every role within the mount to be used.  If the `default_directory_policy`
   specifies a role, it must be allowed under this configuration.

 - `default_directory_policy` `(string: "sign-verbatim")` - Specifies the
   behavior of the default ACME directory.  Can be `forbid`, `sign-verbatim`
   or a role given by `role:<role_name>`.  If a role is used, it must be
   present in `allowed_roles`.

 - `dns_resolver` `(string: "")` - An optional overriding DNS resolver to
   use for challenge verification lookups. When not specified, the default
   system resolver will be used. This allows domains on peered networks with
   an accessible DNS resolver to be validated.

 - `eab_policy` `(string: "not-required")` - Specified policy to enforce
   around [External Account Bindings (EABs)](#acme-external-account-bindings).
   The allowed values are:

     - `not-required`, where EABs are not enforced but are validated if
        specified.

     - `new-account-required`, where new accounts are required to have EAB
       but existing accounts can still be used.

     - `always-required`, where all accounts regardless of age are required
       to have EABs set.

 - `enabled` `(bool: false)` - Whether ACME is enabled on this mount. When
   ACME is disabled, all requests to ACME directory URLs will return 404.

#### Sample payload

```
{
    "enabled": true
}
```

#### Sample request

```
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/config/acme
```

#### Sample response

```
{
  "data": {
    "allowed_issuers": [
      "*"
    ],
    "allowed_roles": [
      "*"
    ],
    "default_directory_policy": "sign-verbatim",
    "dns_resolver": "",
    "eab_policy": "not-required",
    "enabled": true
  }
}
```

## Issuing certificates

The following API endpoints allow users or operators to request certificates
and are all authenticated.

In general, for self-serve use, the `/pki/sign/:name` and `/pki/issue/:name`
are sufficient to allow most users to access for ACL purposes. The per-issuer
variants (`/pki/issuer/:issuer_ref/sign/:name` and
`/pki/issuer/:issuer_ref/issue/:name`) allow the requester to override the
role's chosen issuer, potentially allowing users to request certificates
issued by the wrong parent authority.

Some API endpoints included here are privileged and should only be accessed
by trusted users or operators; these include the various `sign-verbatim`,
`sign-self-signed` and `sign-intermediate` endpoints.

If an issued certificate has been compromised, it should be revoked. The
Vault PKI secrets engine presently only allows revocation by serial number;
because this could allow users to deny access to other users, it should be
restricted to operators.

### List roles

This endpoint returns a list of available roles. Only the role names are
returned, not any values. It is useful to both operators and users.

| Method | Path         |
| :----- | :----------- |
| `LIST` | `/pki/roles` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request LIST \
    http://127.0.0.1:8200/v1/pki/roles
```

#### Sample response

```json
{
  "auth": null,
  "data": {
    "keys": ["dev", "prod"]
  },
  "lease_duration": 0,
  "lease_id": "",
  "renewable": false
}
```

### Read role

This endpoint queries the role definition. It is useful to both operators and
users.

| Method | Path               |
| :----- | :----------------- |
| `GET`  | `/pki/roles/:name` |

#### Parameters

- `name` `(string: <required>)` - Specifies the name of the role to read. This
  is part of the request URL.

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/roles/my-role
```

#### Sample response

```json
{
  "data": {
    "allow_any_name": false,
    "allow_ip_sans": true,
    "allow_localhost": true,
    "allow_subdomains": false,
    "allowed_domains": ["example.com", "foobar.com"],
    "allowed_uri_sans": ["example.com", "spiffe://*"],
    "allowed_other_sans": [
      "1.3.6.1.4.1.311.20.2.3;utf8:devops@example.com",
      "1.3.6.1.4.1.311.20.2.4;UTF-8:*"
    ],
    "client_flag": true,
    "code_signing_flag": false,
    "key_bits": 2048,
    "key_type": "rsa",
    "ttl": "6h",
    "max_ttl": "12h",
    "server_flag": true,
    ... additional fields elided ...
  }
}
```

<a name="generate-certificate"></a>

### Generate certificate and key

This endpoint generates a new set of credentials (private key and certificate)
based on the role named in the endpoint. The issuing CA certificate and full CA
chain is returned as well, so that only the root CA need be in a client's trust
store. Choice of issuing CA is determined first by the role (when using the
`/pki/issue/:name` path) and then by the path (when using the
`/pki/issuer/:issuer_ref/issue/name` path).

It is suggested to limit access to the path-overridden issue endpoint (on
`/pki/issuer/:issuer_ref/issue/:name`).

~> **Note**: The private key is _not_ stored. If you do not save the private
   key from the response, you will need to request a new certificate.

| Method | Path                                  | Issuer        |
| :----- | :------------------------------------ | :------------ |
| `POST` | `/pki/issue/:name`                    | Role selected |
| `POST` | `/pki/issuer/:issuer_ref/issue/:name` | Path selected |

#### Parameters

- `name` `(string: <required>)` - Specifies the name of the role to create the
  certificate against. This is part of the request URL.

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.

~> Note: This parameter is not present on the `/pki/issue/:name` path and
   takes its value from the role's `issuer_ref` field.

- `common_name` `(string: "")` - Specifies the requested CN for the
  certificate. If the CN is allowed by role policy, it will be issued. If more
  than one `common_name` is desired, specify the alternative names in the
  `alt_names` list.

~> Note: A value for `common_name` is required when [require_cn](#require_cn) is set to `true`

- `alt_names` `(string: "")` - Specifies requested Subject Alternative Names, in
  a comma-delimited list. These can be host names or email addresses; they will
  be parsed into their respective fields. If any requested names do not match
  role policy, the entire request will be denied.

- `ip_sans` `(string: "")` - Specifies requested IP Subject Alternative Names,
  in a comma-delimited list. Only valid if the role allows IP SANs (which is the
  default).

- `uri_sans` `(string: "")` - Specifies the requested URI Subject Alternative
  Names, in a comma-delimited list. If any requested URIs do not match role policy,
  the entire request will be denied.

- `other_sans` `(string: "")` - Specifies custom OID/UTF8-string SANs. These
  must match values specified on the role in `allowed_other_sans` (see role
  creation for allowed_other_sans globbing rules).
  The format is the same as OpenSSL: `<oid>;<type>:<value>` where the
  only current valid type is `UTF8`. This can be a comma-delimited list or a
  JSON string slice.

- `ttl` `(string: "")` - Specifies requested Time To Live. Cannot be greater
  than the role's `max_ttl` value. If not provided, the role's `ttl` value will
  be used. Note that the role values default to system values if not explicitly
  set. See `not_after` as an alternative for setting an absolute end date
  (rather than a relative one).

- `format` `(string: "pem")` - Specifies the format for returned data. Can be
  `pem`, `der`, or `pem_bundle`; defaults to `pem`. If `der`, the output is
  base64 encoded. If `pem_bundle`, the `certificate` field will contain the
  private key and certificate, concatenated; if the issuing CA is not a
  Vault-derived self-signed root, this will be included as well.

- `private_key_format` `(string: "der")` - Specifies the format for marshaling
  the private key within the private_key response field. Defaults to `der` which will
  return either base64-encoded DER or PEM-encoded DER, depending on the value of
  `format`. The other option is `pkcs8` which will return the key marshalled as
  PEM-encoded PKCS8.

~> **Note** that this does not apply to the private key within the certificate
  field if `format=pem_bundle` parameter is specified.

- `exclude_cn_from_sans` `(bool: false)` - If true, the given `common_name` will
  not be included in DNS or Email Subject Alternate Names (as appropriate).
  Useful if the CN is not a hostname or email address, but is instead some
  human-readable identifier.

- `not_after` `(string)` - Set the Not After field of the certificate with
  specified date value. The value format should be given in UTC format
  `YYYY-MM-ddTHH:MM:SSZ`. Supports the Y10K end date for IEEE 802.1AR-2018
  standard devices, `9999-12-31T23:59:59Z`.

- `remove_roots_from_chain` `(bool: false)` - If true, the returned `ca_chain`
  field will not include any self-signed CA certificates. Useful if end-users
  already have the root CA in their trust store.

- `user_ids` `(string: "")` - Specifies the comma-separated list of requested
  User ID (OID 0.9.2342.19200300.100.1.1) Subject values to be placed on the
  signed certificate. This field is validated against `allowed_user_ids` on
  the role.

#### Sample payload

```json
{
  "common_name": "www.example.com"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/issue/my-role
```

#### Sample response

```json
{
  "lease_id": "pki/issue/test/7ad6cfa5-f04f-c62a-d477-f33210475d05",
  "renewable": false,
  "lease_duration": 21600,
  "data": {
    "expiration": "1654105687",
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE-----\n",
    "issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n",
    "ca_chain": [
      "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n"
    ],
    "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAnVHfwoKsUG1GDVyWB1AFroaKl2ImMBO8EnvGLRrmobIkQvh+\n...\nQN351pgTphi6nlCkGPzkDuwvtxSxiCWXQcaxrHAL7MiJpPzkIBq1\n-----END RSA PRIVATE KEY-----\n",
    "private_key_type": "rsa",
    "serial_number": "39:dd:2e:90:b7:23:1f:8d:d3:7d:31:c5:1b:da:84:d0:5b:65:31:58"
  },
  "warnings": "",
  "auth": null
}
```

### Generate certificate and key with external policy <EnterpriseAlert inline="true" />

Similar to the [generate certificate and key](#generate-certificate-and-key)
endpoint, this endpoint generate key material and certificate via an external
policy engine. The private key material stays local to Vault, with the external
service getting only an empty CSR. Any parameters passed to this endpoint are
passed verbatim to the Certificate Issuance External
Policy Service (CIEPS)<EnterpriseAlert inline="true" />. The
response format is the same between both endpoints.

It is suggested to limit access to the path-overridden issue endpoint (on
`/pki/issuer/:issuer_ref/external-policy/issue/:policy`) and let the CIEPS
engine override the issuer as necessary.

| Method | Path                                                      | Issuer                      |
| :----- |:----------------------------------------------------------| :-------------------------- |
| `POST` | `/pki/external-policy/issue(/:policy)`                    | `default` or CIEPS-selected |
| `POST` | `/pki/issuer/:issuer_ref/external-policy/issue(/:policy)` | Path or CIEPS selected      |

#### Parameters

- `policy` `(string: <optional>)` - Specifies the name of the policy to create
  the certificate against. This is part of the request URL and is passed to the
  external CIEPS engine.

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.

~> Note: This parameter is not present on the `/pki/external-policy/sign/:policy`
   path and takes its value from the CIEPS engine response's `issuer_ref`
   field, which can override the user-requested issuer.

- `format` `(string: "pem")` - Specifies the format for returned data. Can be
  `pem`, `der`, or `pem_bundle`; defaults to `pem`. If `der`, the output is
  base64 encoded. If `pem_bundle`, the `certificate` field will contain the
  private key and certificate, concatenated; if the issuing CA is not a
  Vault-derived self-signed root, this will be included as well.

- `key_type` `(string: "rsa")` - Specifies the desired key type; must be `rsa`, `ed25519`
  or `ec`.

~> **Note**: In FIPS 140-2 mode, the following algorithms are not certified
   and thus should not be used: `ed25519`.

- `key_bits` `(int: 0)` - Specifies the number of bits to use for the
  generated keys. Allowed values are 0 (universal default); with
  `key_type=rsa`, allowed values are: 2048 (default), 3072, or
  4096; with `key_type=ec`, allowed values are: 224, 256 (default),
  384, or 521; ignored with `key_type=ed25519`.

- `private_key_format` `(string: "der")` - Specifies the format for marshaling
  the private key within the private_key response field. Defaults to `der` which will
  return either base64-encoded DER or PEM-encoded DER, depending on the value of
  `format`. The other option is `pkcs8` which will return the key marshalled as
  PEM-encoded PKCS8.

~> **Note** that this does not apply to the private key within the certificate
  field if `format=pem_bundle` parameter is specified.


- `remove_roots_from_chain` `(bool: false)` - If true, the returned `ca_chain`
  field will not include any self-signed CA certificates. Useful if end-users
  already have the root CA in their trust store.

Other parameters may be specified and will not be parsed by Vault but may be
recognized based on external CIEPS engine definition.

#### Sample payload

```json
{
  "common_name": "example.com",
  "key_type": "rsa",
  "key_bits": 2048
}
```

#### Sample response

```json
{
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "expiration": "1654105687",
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE-----\n",
    "issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n",
    "ca_chain": [
      "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n"
    ],
    "serial_number": "39:dd:2e:90:b7:23:1f:8d:d3:7d:31:c5:1b:da:84:d0:5b:65:31:52"
  },
  "auth": null
}
```

### Sign certificate

This endpoint signs a new certificate based upon the provided CSR and the
supplied parameters, subject to the restrictions contained in the role named in
the endpoint. The issuing CA certificate and the full CA chain is returned as
well, so that only the root CA need be in a client's trust store.

It is suggested to limit access to the path-overridden sign endpoint (on
`/pki/issuer/:issuer_ref/sign/:name`).

| Method | Path                                 | Issuer        |
| :----- | :----------------------------------- | :------------ |
| `POST` | `/pki/sign/:name`                    | Role selected |
| `POST` | `/pki/issuer/:issuer_ref/sign/:name` | Path selected |

#### Parameters

- `name` `(string: <required>)` - Specifies the name of the role to create the
  certificate against. This is part of the request URL.

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.

~> Note: This parameter is not present on the `/pki/sign/:name` path and
   takes its value from the role's `issuer_ref` field.

- `csr` `(string: <required>)` - Specifies the PEM-encoded CSR.

- `common_name` `(string: <required>)` - Specifies the requested CN for the
  certificate. If the CN is allowed by role policy, it will be issued. If
  more than one `common_name` is desired, specify the alternative names in
  the `alt_names` list.

- `alt_names` `(string: "")` - Specifies the requested Subject Alternative
  Names, in a comma-delimited list. These can be host names or email addresses;
  they will be parsed into their respective fields. If any requested names do
  not match role policy, the entire request will be denied.

- `other_sans` `(string: "")` - Specifies custom OID/UTF8-string SANs. These
  must match values specified on the role in `allowed_other_sans` (see role
  creation for allowed_other_sans globbing rules).
  The format is the same as OpenSSL: `<oid>;<type>:<value>` where the
  only current valid type is `UTF8`. This can be a comma-delimited list or a
  JSON string slice.

- `ip_sans` `(string: "")` - Specifies the requested IP Subject Alternative
  Names, in a comma-delimited list. Only valid if the role allows IP SANs (which
  is the default).

- `uri_sans` `(string: "")` - Specifies the requested URI Subject Alternative
  Names, in a comma-delimited list. If any requested URIs do not match role policy,
  the entire request will be denied.

- `ttl` `(string: "")` - Specifies the requested Time To Live. Cannot be greater
  than the role's `max_ttl` value. If not provided, the role's `ttl` value will
  be used. Note that the role values default to system values if not explicitly
  set. See `not_after` as an alternative for setting an absolute end date
  (rather than a relative one).

- `format` `(string: "pem")` - Specifies the format for returned data. Can be
  `pem`, `der`, or `pem_bundle`. If `der`, the output is base64 encoded. If
  `pem_bundle`, the `certificate` field will contain the certificate and, if the
  issuing CA is not a Vault-derived self-signed root, it will be concatenated
  with the certificate.

- `exclude_cn_from_sans` `(bool: false)` - If true, the given `common_name` will
  not be included in DNS or Email Subject Alternate Names (as appropriate).
  Useful if the CN is not a hostname or email address, but is instead some
  human-readable identifier.

- `not_after` `(string)` - Set the Not After field of the certificate with
  specified date value. The value format should be given in UTC format
  `YYYY-MM-ddTHH:MM:SSZ`. Supports the Y10K end date for IEEE 802.1AR-2018
  standard devices, `9999-12-31T23:59:59Z`.

- `remove_roots_from_chain` `(bool: false)` - If true, the returned `ca_chain`
  field will not include any self-signed CA certificates. Useful if end-users
  already have the root CA in their trust store.

- `user_ids` `(string: "")` - Specifies the comma-separated list of requested
  User ID (OID 0.9.2342.19200300.100.1.1) Subject values to be placed on the
  signed certificate. This field is validated against `allowed_user_ids` on
  the role.

#### Sample payload

```json
{
  "csr": "...",
  "common_name": "example.com"
}
```

#### Sample response

```json
{
  "lease_id": "pki/sign/test/7ad6cfa5-f04f-c62a-d477-f33210475d05",
  "renewable": false,
  "lease_duration": 21600,
  "data": {
    "expiration": "1654105687",
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE-----\n",
    "issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n",
    "ca_chain": [
      "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n"
    ],
    "serial_number": "39:dd:2e:90:b7:23:1f:8d:d3:7d:31:c5:1b:da:84:d0:5b:65:31:58"
  },
  "auth": null
}
```

### Sign certificate with external policy <EnterpriseAlert inline="true" />

Similar to the [sign certificate](#sign-certificate) endpoint, this endpoint
signs the specified leaf CSR via an external policy engine. Any parameters
passed to this endpoint are passed verbatim to the Certificate Issuance External
Policy Service (CIEPS)<EnterpriseAlert inline="true" />. The response format is the same
between both endpoints.

It is suggested to limit access to the path-overridden sign endpoint (on
`/pki/issuer/:issuer_ref/external-policy/sign/:policy`) and let the CIEPS
engine override the issuer as necessary.

| Method | Path                                                     | Issuer                      |
| :----- |:---------------------------------------------------------| :-------------------------- |
| `POST` | `/pki/external-policy/sign(/:policy)`                    | `default` or CIEPS-selected |
| `POST` | `/pki/issuer/:issuer_ref/external-policy/sign(/:policy)` | Path or CIEPS selected      |

#### Parameters

- `policy` `(string: <optional>)` - Specifies the name of the policy to create
  the certificate against. This is part of the request URL and is passed to the
  external CIEPS engine.

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.

~> Note: This parameter is not present on the `/pki/external-policy/sign/:policy`
   path and takes its value from the CIEPS engine response's `issuer_ref`
   field, which can override the user-requested issuer.

- `csr` `(string: <required>)` - Specifies the PEM-encoded CSR.

- `format` `(string: "pem")` - Specifies the format for returned data. Can be
  `pem`, `der`, or `pem_bundle`; defaults to `pem`. If `der`, the output is
  base64 encoded. If `pem_bundle`, the `certificate` field will contain the
  private key and certificate, concatenated; if the issuing CA is not a
  Vault-derived self-signed root, this will be included as well.

- `private_key_format` `(string: "der")` - Specifies the format for marshaling
  the private key within the private_key response field. Defaults to `der` which will
  return either base64-encoded DER or PEM-encoded DER, depending on the value of
  `format`. The other option is `pkcs8` which will return the key marshalled as
  PEM-encoded PKCS8.

~> **Note** that this does not apply to the private key within the certificate
  field if `format=pem_bundle` parameter is specified.

- `remove_roots_from_chain` `(bool: false)` - If true, the returned `ca_chain`
  field will not include any self-signed CA certificates. Useful if end-users
  already have the root CA in their trust store.

Other parameters may be specified and will not be parsed by Vault but may be
recognized based on external CIEPS engine definition.

#### Sample payload

```json
{
  "csr": "...",
  "common_name": "example.com",
  "key_attestation": "..."
}
```

#### Sample response

```json
{
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "expiration": "1654105687",
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE-----\n",
    "issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n",
    "ca_chain": [
      "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n"
    ],
    "serial_number": "39:dd:2e:90:b7:23:1f:8d:d3:7d:31:c5:1b:da:84:d0:5b:65:31:52"
  },
  "auth": null
}
```

### Sign intermediate

This endpoint uses the configured CA certificate to issue a certificate with
appropriate values for acting as an intermediate CA. Distribution points use the
values set via `config/urls`. Values set in the CSR are ignored unless
`use_csr_values` is set to true, in which case the values from the CSR are used
verbatim.

This endpoint can be used both when signing a Vault-backed intermediate or
when signing an externally-owned intermediate.

~> **Note**: This is a privileged endpoint, as callers are granted a new
   intermediate certificate, with which they can issue for arbitrary names.
   Access to this endpoint should be restricted by policy to only trusted
   operators.

| Method | Path                                        | Issuer    |
| :----- | :------------------------------------------ | :-------  |
| `POST` | `/pki/root/sign-intermediate`               | `default` |
| `POST` | `/pki/issuer/:issuer_ref/sign-intermediate` | Selected  |

#### Parameters

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.

~> Note: This parameter is not present on the `/pki/root/sign-intermediate`
   path and takes the value `default`.

- `csr` `(string: <required>)` - Specifies the PEM-encoded CSR to be signed.

- `common_name` `(string: <required>)` - Specifies the requested CN for the
  certificate. If more than one `common_name` is desired, specify the
  alternative names in the `alt_names` list.

- `alt_names` `(string: "")` - Specifies the requested Subject Alternative
  Names, in a comma-delimited list. These can be host names or email addresses;
  they will be parsed into their respective fields.

- `ip_sans` `(string: "")` - Specifies the requested IP Subject Alternative
  Names, in a comma-delimited list.

- `uri_sans` `(string: "")` - Specifies the requested URI Subject Alternative
  Names, in a comma-delimited list.

- `other_sans` `(string: "")` - Specifies custom OID/UTF8-string SANs. These
  must match values specified on the role in `allowed_other_sans` (see role
  creation for allowed_other_sans globbing rules).
  The format is the same as OpenSSL: `<oid>;<type>:<value>` where the
  only current valid type is `UTF8`. This can be a comma-delimited list or a
  JSON string slice.

- `ttl` `(string: "")` - Specifies the requested Time To Live (after which the
  certificate will be expired). This cannot be larger than the engine's max (or,
  if not set, the system max). However, this can be after the expiration of the
  signing CA. See `not_after` as an alternative for setting an absolute end date
  (rather than a relative one).

- `format` `(string: "pem")` - Specifies the format for returned data. Can be
  `pem`, `der`, or `pem_bundle`. If `der`, the output is base64 encoded. If
  `pem_bundle`, the `certificate` field will contain the certificate and, if the
  issuing CA is not a Vault-derived self-signed root, it will be concatenated
  with the certificate.

- `max_path_length` `(int: -1)` - Specifies the maximum path length to encode in
  the generated certificate. `-1`, means no limit, unless the signing
  certificate has a maximum path length set, in which case the path length is
  set to one less than that of the signing certificate. A limit of `0` means a
  literal path length of zero.

- `exclude_cn_from_sans` `(bool: false)` - If true, the given `common_name` will
  not be included in DNS or Email Subject Alternate Names (as appropriate).
  Useful if the CN is not a hostname or email address, but is instead some
  human-readable identifier.

- `use_csr_values` `(bool: false)` - If set to `true`, then: 1) Subject
  information, including names and alternate names, will be preserved from the
  CSR rather than using the values provided in the other parameters to this
  path; 2) Any key usages (for instance, non-repudiation) requested in the CSR
  will be added to the basic set of key usages used for CA certs signed by this
  path; 3) Extensions requested in the CSR will be copied into the issued
  certificate.

- `permitted_dns_domains` `(string: "")` - A comma separated string (or, string
  array) containing DNS domains for which certificates are allowed to be issued
  or signed by this CA certificate. Supports subdomains via a `.` in front of
  the domain, as per [RFC 5280 Section 4.2.1.10 - Name
  Constraints](https://tools.ietf.org/html/rfc5280#section-4.2.1.10)

- `ou` `(string: "")` - Specifies the OU (OrganizationalUnit) values in the
  subject field of the resulting certificate. This is a comma-separated string
  or JSON array.

- `organization` `(string: "")` - Specifies the O (Organization) values in the
  subject field of the resulting certificate. This is a comma-separated string
  or JSON array.

- `country` `(string: "")` - Specifies the C (Country) values in the subject
  field of the resulting certificate. This is a comma-separated string or JSON
  array.

- `locality` `(string: "")` - Specifies the L (Locality) values in the subject
  field of the resulting certificate. This is a comma-separated string or JSON
  array.

- `province` `(string: "")` - Specifies the ST (Province) values in the subject
  field of the resulting certificate. This is a comma-separated string or JSON
  array.

- `street_address` `(string: "")` - Specifies the Street Address values in the
  subject field of the resulting certificate. This is a comma-separated string
  or JSON array.

- `postal_code` `(string: "")` - Specifies the Postal Code values in the
  subject field of the resulting certificate. This is a comma-separated string
  or JSON array.

- `serial_number` `(string: "")` -  - Specifies the requested Subject's named
  [Serial Number](https://datatracker.ietf.org/doc/html/rfc4519#section-2.31)
  value, if any. If you want more than one, specify alternative names in the
  `alt_names` map using OID 2.5.4.5. Note that this has no impact on the
  Certificate's serial number field, which Vault randomly generates.

- `not_before_duration` `(duration: "30s")` - Specifies the duration by which to
  backdate the NotBefore property. This value has no impact in the validity period
  of the requested certificate, specified in the `ttl` field.
  Uses [duration format strings](/vault/docs/concepts/duration-format).

- `not_after` `(string)` - Set the Not After field of the certificate with
  specified date value. The value format should be given in UTC format
  `YYYY-MM-ddTHH:MM:SSZ`. Supports the Y10K end date for IEEE 802.1AR-2018
  standard devices, `9999-12-31T23:59:59Z`.

- `signature_bits` `(int: 0)` - Specifies the number of bits to use in
  the signature algorithm; accepts 256 for SHA-2-256, 384 for SHA-2-384,
  and 512 for SHA-2-512. Defaults to 0 to automatically detect based
  on issuer's key length (SHA-2-256 for RSA keys, and matching the curve size
  for NIST P-Curves).

~> **Note**: ECDSA and Ed25519 issuers do not follow configuration of the
   `signature_bits` value; only RSA issuers will change signature types
   based on this parameter.

- `skid` `(string: "")` - Value for the Subject Key Identifier field
  (RFC 5280 Section 4.2.1.2). Specified as a string in hex format. Default
  is empty, allowing Vault to automatically calculate the SKID according
  to method one in the above RFC section.

~> **Note**: This value should ONLY be used when cross-signing to mimic
   the existing certificate's SKID value; this is necessary to allow
   certain TLS implementations (such as OpenSSL) which use SKID/AKID
   matches in chain building to restrict possible valid chains.

- `use_pss` `(bool: false)` - Specifies whether or not to use PSS signatures
  over PKCS#1v1.5 signatures when a RSA-type issuer is used. Ignored for
  ECDSA/Ed25519 issuers.

#### Sample payload

```json
{
  "csr": "...",
  "common_name": "example.com"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/root/sign-intermediate
```

#### Sample response

```json
{
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "expiration": "1654105687",
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE-----\n",
    "issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n",
    "ca_chain": [
      "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n"
    ],
    "serial_number": "39:dd:2e:90:b7:23:1f:8d:d3:7d:31:c5:1b:da:84:d0:5b:65:31:58"
  },
  "auth": null
}
```

### Sign Intermediate with External Policy <EnterpriseAlert inline="true" />

Similar to [sign intermediate](#sign-intermediate), this endpoint accepts a
CSR and returns a certificate with appropriate values for acting as an
intermediate CA via an external policy engine. Any parameters passed to this
endpoint are passed verbatim to the Certificate Issuance External Policy Service
(CIEPS)<EnterpriseAlert inline="true" />.
The response format is the same between both endpoints.

It is suggested to limit access to the path-overridden issue endpoint
(on /pki/issuer/:issuer_ref/external-policy/issue/:policy) and let the CIEPS
engine override the issuer as necessary.

| Method | Path                                                                | Issuer                    |
|--------|---------------------------------------------------------------------|---------------------------|
| POST   | /pki/external-policy/sign-intermediate(/:policy)                    | default or CIEPS-selected |
| POST   | /pki/issuer/:issuer_ref/external-policy/sign-intermediate(/:policy) | Path or CIEPS selected    |

#### Parameters

- `policy` `(string: <optional>)` - Specifies the name of the policy to create
  the certificate against. This is part of the request URL and is passed to the
  external CIEPS engine.

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.

~> Note: This parameter is not present on the `/pki/external-policy/sign-intermediate`
path and takes its value from the CIEPS engine response's `issuer_ref`
field, which can override the user-requested issuer.

- `csr` `(string: <required>)` - Specifies the PEM-encoded CSR.

- `format` `(string: "pem")` - Specifies the format for returned data. Can be
  `pem`, `der`, or `pem_bundle`; defaults to `pem`. If `der`, the output is
  base64 encoded. If `pem_bundle`, the `certificate` field will contain the
  private key and certificate, concatenated; if the issuing CA is not a
  Vault-derived self-signed root, this will be included as well.

- `private_key_format` `(string: "pem")` - Specifies the format for marshaling
  the private key within the private_key response field. Defaults to `der` which will
  return either base64-encoded DER or PEM-encoded DER, depending on the value of
  `format`. The other option is `pkcs8` which will return the key marshalled as
  PEM-encoded PKCS8.

~> **Note** that this does not apply to the private key within the certificate
field if `format=pem_bundle` parameter is specified.

Other parameters may be specified and will not be parsed by Vault but may be
recognized based on external CIEPS engine definition.

#### Sample payload

```json
{
  "csr": "..."
}
```

#### Sample response

```json
{
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "expiration": "1654105687",
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE-----\n",
    "issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n",
    "ca_chain": [
      "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n"
    ],
    "serial_number": "39:dd:2e:90:b7:23:1f:8d:d3:7d:31:c5:1b:da:84:d0:5b:65:31:58"
  },
  "auth": null
}
```

### Sign Self-Issued

This endpoint uses the configured CA certificate to sign a self-issued
certificate (which will usually be a self-signed certificate as well).

~> **_This is an extremely privileged endpoint_**. The given certificate will be
   signed as-is with only minimal validation performed (is it a CA cert, and is it
   actually self-issued). The only values that will be changed will be the
   authority key ID, the issuer DN, and, if set, any distribution points.<br /><br />
   It is recommended to limit this endpoint to only trusted operators.

This is generally only needed for root certificate rolling in cases where you
don't want/can't get access to a CSR (such as if it's a root stored in Vault
where the key is not exposed). If you don't know whether you need this
endpoint, you most likely should be using a different endpoint (such as
`sign-intermediate`).

| Method | Path                                       | Issuer    | Requires `sudo` capability |
| :----- | :----------------------------------------- | :-------- | :------------------------- |
| `POST` | `/pki/root/sign-self-issued`               | `default` | yes                        |
| `POST` | `/pki/issuer/:issuer_ref/sign-self-issued` | Selected  | no                         |

#### Parameters

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.

~> Note: This parameter is not present on the `/pki/root/sign-self-issued`
   path and takes the value `default`.

- `certificate` `(string: <required>)` - Specifies the PEM-encoded self-issued certificate.

- `require_matching_certificate_algorithms` `(bool: false)` - If true, requires
that the public key algorithm of the CA match that of the submitted certificate.

#### Sample payload

```json
{
  "certificate": "..."
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/root/sign-self-issued
```

#### Sample response

```json
{
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE-----\n",
    "issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n"
  },
  "auth": null
}
```

### Sign verbatim

This endpoint signs a new certificate based upon the provided CSR. Values are
taken verbatim from the CSR; the _only_ restriction is that this endpoint will
refuse to issue an intermediate CA certificate (see the
`/pki/root/sign-intermediate` endpoint for that functionality.)

**This is a potentially dangerous endpoint and only highly trusted users should
have access.**

| Method | Path                                            | Issuer    |
| :----- | :---------------------------------------------- | :-------- |
| `POST` | `/pki/sign-verbatim(/:name)`                    | `default` |
| `POST` | `/pki/issuer/:issuer_ref/sign-verbatim(/:name)` | Selected  |

#### Parameters

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.

~> Note: This parameter is not present on the `/pki/root/sign-self-issued`
   path and takes the value `default`.

- `name` `(string: "")` - Specifies a role. If set, the following parameters
  from the role will have effect: `ttl`, `max_ttl`, `generate_lease`, `no_store` and `not_before_duration`.

- `csr` `(string: <required>)` - Specifies the PEM-encoded CSR.

- `key_usage` `(list: ["DigitalSignature", "KeyAgreement", "KeyEncipherment"])` -
  Specifies the default key usage constraint on the issued certificate. Valid
  values can be found at https://golang.org/pkg/crypto/x509/#KeyUsage - simply
  drop the `KeyUsage` part of the value. Values are not case-sensitive. To
  specify no default key usage constraints, set this to an empty list.

~> Note: previous versions of this document incorrectly called this a constraint;
   this value is only used as a default when the `KeyUsage` extension is missing
   from the CSR.

- `ext_key_usage` `(list: [])` -
  Specifies the default extended key usage constraint on the issued certificate. Valid
  values can be found at https://golang.org/pkg/crypto/x509/#ExtKeyUsage - simply
  drop the `ExtKeyUsage` part of the value. Values are not case-sensitive. To
  specify no key default usage constraints, set this to an empty list.

~> Note: previous versions of this document incorrectly called this a constraint;
   this value is only used as a default when the `ExtendedKeyUsage` extension is
   missing from the CSR.

- `ext_key_usage_oids` `(string: "")` - A comma-separated string or list of extended key usage oids.

~> Note: This value is only used as a default when the `ExtendedKeyUsage`
   extension is missing from the CSR.

- `ttl` `(string: "")` - Specifies the requested Time To Live. Cannot be greater
  than the engine's `max_ttl` value. If not provided, the engine's `ttl` value
  will be used, which defaults to system values if not explicitly set. See
  `not_after` as an alternative for setting an absolute end date (rather than
  a relative one).

- `format` `(string: "pem")` - Specifies the format for returned data. Can be
  `pem`, `der`, or `pem_bundle`. If `der`, the output is base64 encoded. If
  `pem_bundle`, the `certificate` field will contain the certificate and, if the
  issuing CA is not a Vault-derived self-signed root, it will be concatenated
  with the certificate.

- `not_after` `(string)` - Set the Not After field of the certificate with
  specified date value. The value format should be given in UTC format
  `YYYY-MM-ddTHH:MM:SSZ`. Supports the Y10K end date for IEEE 802.1AR-2018
  standard devices, `9999-12-31T23:59:59Z`.

- `signature_bits` `(int: 0)` - Specifies the number of bits to use in
  the signature algorithm; accepts 256 for SHA-2-256, 384 for SHA-2-384,
  and 512 for SHA-2-512. Defaults to 0 to automatically detect based
  on issuer's key length (SHA-2-256 for RSA keys, and matching the curve size
  for NIST P-Curves).

~> **Note**: ECDSA and Ed25519 issuers do not follow configuration of the
   `signature_bits` value; only RSA issuers will change signature types
   based on this parameter.

- `use_pss` `(bool: false)` - Specifies whether or not to use PSS signatures
  over PKCS#1v1.5 signatures when a RSA-type issuer is used. Ignored for
  ECDSA/Ed25519 issuers.

- `remove_roots_from_chain` `(bool: false)` - If true, the returned `ca_chain`
  field will not include any self-signed CA certificates. Useful if end-users
  already have the root CA in their trust store.

- `user_ids` `(string: "")` - Specifies the comma-separated list of requested
  User ID (OID 0.9.2342.19200300.100.1.1) Subject values to be placed on the
  signed certificate. No validation on names is performed using this endpoint.

#### Sample payload

```json
{
  "csr": "..."
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/sign-verbatim
```

#### Sample response

```json
{
  "lease_id": "pki/sign-verbatim/7ad6cfa5-f04f-c62a-d477-f33210475d05",
  "renewable": false,
  "lease_duration": 21600,
  "data": {
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE-----\n",
    "issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n",
    "ca_chain": [
      "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n"
    ],
    "serial_number": "39:dd:2e:90:b7:23:1f:8d:d3:7d:31:c5:1b:da:84:d0:5b:65:31:58"
  },
  "auth": null
}
```

### Revoke certificate

This endpoint revokes a certificate using its serial number. This is an
alternative option to the standard method of revoking using Vault lease IDs. A
successful revocation will rotate the CRL.

~> **Note**: This operation is privileged as it allows revocation of arbitrary
   certificates based purely on their serial number. It does not validate that
   the requesting user issued the certificate or has possession of the private
   key.<br /><br />
   It is not possible to revoke issuers using this path.

| Method | Path          |
| :----- | :------------ |
| `POST` | `/pki/revoke` |

#### Parameters

~> Note: either `serial_number` or `certificate` (but not both) must be
   specified on requests to this endpoint.

- `serial_number` `(string: <optional>)` - Specifies the serial number of the
  certificate to revoke, in hyphen-separated or colon-separated hexadecimal.

- `certificate` `(string: <optional>)` - Specifies the certificate to revoke,
  in PEM format. This certificate must have been signed by one of the issuers
  in this mount in order to be accepted for revocation.

#### Sample payload

```json
{
  "serial_number": "39:dd:2e..."
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/revoke
```

#### Sample response

```json
{
  "data": {
    "revocation_time": 1433269787
  }
}
```

### Revoke certificate with private key

This endpoint revokes a certificate using its private key as proof that the
request is authorized by an appropriate individual (Proof of Possession).

This is an alternative option to the standard method of revoking using Vault
lease IDs or revocation via serial number. A successful revocation will
rotate the CRL.

It is not possible to revoke issuers using this path.

~> **Note**: This operation is **NOT** privileged, as it validates revocation
   has a private key corresponding to a certificate signed by Vault. However,
   to avoid third parties performing a denial-of-service (DOS) against Vault,
   we've made this endpoint authenticated. Thus it is strongly encouraged to
   generally allow all access to this path via ACLs.

| Method | Path                   |
| :----- | :--------------------- |
| `POST` | `/pki/revoke-with-key` |

#### Parameters

~> Note: either `serial_number` or `certificate` (but not both) must be
   specified on requests to this endpoint.

- `serial_number` `(string: <optional>)` - Specifies the serial number of the
  certificate to revoke, in hyphen-separated or colon-separated hexadecimal.

- `certificate` `(string: <optional>)` - Specifies the certificate to revoke,
  in PEM format. This certificate must have been signed by one of the issuers
  in this mount in order to be accepted for revocation.

- `private_key` `(string: <required>)` - Specifies the private key (in PEM
  format) corresponding to the certificate issued by Vault that is attempted
  to be revoked. This endpoint must be called several times (with each unique
  certificate/serial number) if this private key is used in multiple
  certificates as Vault does not maintain such a mapping.

#### Sample payload

```json
{
  "serial_number": "39:dd:2e...",
  "private_key": "-----BEGIN PRIVATE KEY-----\n..."
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/revoke-with-key
```

#### Sample response

```json
{
  "data": {
    "revocation_time": 1433269787
  }
}
```


### List revoked certificates

This endpoint returns a list of serial numbers that have been revoked on the local cluster.

| Method | Path              |
|:-------|:------------------|
| `LIST` | `/certs/revoked`  |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request LIST \
    http://127.0.0.1:8200/v1/pki/certs/revoked
```

#### Sample response

```json
{
  "data": {
    "keys": [
      "3d:80:91:c3:c2:34:3b:81:69:3d:92:a3:80:69:db:53:04:26:ab:b4"
    ]
  }
}
```

### List revocation requests

This endpoint returns a list of serial numbers that have been requested to
be revoked on any cluster, along with information about the request's state
and which cluster it originated on.

| Method | Path                      |
| :----- | :------------------------ |
| `LIST` | `/certs/revocation-queue` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request LIST \
    http://127.0.0.1:8200/v1/pki/certs/revocation-queue
```

#### Sample response

```json
{
  "data": {
    "key_info": {
      "3d:80:91:c3:c2:34:3b:81:69:3d:92:a3:80:69:db:53:04:26:ab:b4": {
        "requesting_cluster": "48327b28-8325-6d79-6a0b-4cbaa6f27b4a"
      }
    },
    "keys": [
      "3d:80:91:c3:c2:34:3b:81:69:3d:92:a3:80:69:db:53:04:26:ab:b4"
    ]
  }
}
```

### List Cross-Cluster revocations

This endpoint returns a list of serial numbers that have been revoked on any
cluster, along with the clusters that have a copy of that revoked certificate.

| Method | Path                     |
| :----- | :----------------------- |
| `LIST` | `/certs/unified-revoked` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request LIST \
    http://127.0.0.1:8200/v1/pki/certs/unified-revoked
```

#### Sample response

```json
{
  "data": {
    "key_info": {
      "7f:fd:12:5b:16:29:bb:28:ea:24:bc:a1:80:f7:4e:6e:a0:69:b9:95": {
        "revoking_clusters": [
          "48327b28-8325-6d79-6a0b-4cbaa6f27b4a"
        ]
      }
    },
    "keys": [
      "7f:fd:12:5b:16:29:bb:28:ea:24:bc:a1:80:f7:4e:6e:a0:69:b9:95"
    ]
  }
}
```

---

## Accessing authority information

All consumers of the PKI Secrets Engine mount point will have access to the
following unauthenticated APIs, useful for reading information about the
certificate authority in this mount point.

This includes information about [CA certificates](#read-issuer-certificate),
[their chains](#read-default-issuer-certificate-chain), and [their signed
CRLs](#read-issuer-crl), containing an encoded list of revoked certificates
previously issued by this authority. Individual issued [certificates can
also be read](#read-certificate), assuming their serial number is known.
Finally, the list of issuing certificates is public information in this
mount.

### List issuers

This endpoint returns a list of issuers currently provisioned in this mount.
The response includes both the issuer's identifier as well as the name chosen
by the operators; either can be used to refer to the issuer later.

This endpoint is unauthenticated.

| Method | Path           |
| :----- | :------------- |
| `LIST` | `/pki/issuers` |

#### Sample request

```shell-session
$ curl \
    --request LIST \
    http://127.0.0.1:8200/v1/pki/issuers
```

#### Sample response

```json
{
  "data": {
    "key_info": {
      "1ae8ce9d-2f70-0761-a465-8c9840a247a2": {
        "issuer_name": "imported-root"
      },
      "3dc79a5a-7a6c-70e2-1123-94b88557ba12": {
        "issuer_name": "root-x1"
      }
    },
    "keys": [
      "1ae8ce9d-2f70-0761-a465-8c9840a247a2",
      "3dc79a5a-7a6c-70e2-1123-94b88557ba12"
    ]
  }
}
```

<a name="read-ca-certificate"></a>

### Read issuer certificate

This endpoint retrieves the specified issuer's certificate.

Note that the response differs between the older `/pki/cert/ca`
path and the newer `/pki/issuer/:issuer_ref/json` path; the latter
includes the full `ca_chain` of the issuer, removing the need for a separate
endpoint.

These are unauthenticated endpoints.

~> Note: this endpoint accepts the `If-Modified-Since` header, to respond with
   304 Not Modified when the requested resource has not changed. This header
   needs to be allowed on the PKI mount by tuning the `passthrough_request_headers`
   option. In order for clients to know the last modified time, the response
   header `Last-Modified` needs to be added to the mount tunable
   `allowed_response_headers`.

| Method | Path                           | Issuer    | Format                                                                            |
| :----- | :----------------------------- | :-------- |:----------------------------------------------------------------------------------|
| `GET`  | `/pki/cert/ca`                 | `default` | JSON                                                                              |
| `GET`  | `/pki/ca`                      | `default` | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") |
| `GET`  | `/pki/ca/pem`                  | `default` | PEM [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") |
| `GET`  | `/pki/issuer/:issuer_ref/json` | Selected  | JSON                                                                              |
| `GET`  | `/pki/issuer/:issuer_ref/der`  | Selected  | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") |
| `GET`  | `/pki/issuer/:issuer_ref/pem`  | Selected  | PEM [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") |

#### Parameters

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.

~> Note: This parameter is not present on the `/pki/cert/ca` and
   `/pki/ca(/pem)?` paths and takes the implicit value `default`.

#### Sample request

```shell-session
$ curl \
    http://127.0.0.1:8200/v1/pki/issuer/root-x1/json
```

#### Sample response

```text
{
  "data": {
    "ca_chain": [
      "-----BEGIN CERTIFICATE-----\nMIIDFDCCAfygAwIBAgIUXgxy54mKooz5soqQoRINazH/3pQwDQYJKoZIhvcNAQEL\n...",
      "-----BEGIN CERTIFICATE-----\nMIIDFTCCAf2gAwIBAgIUUo/qwLm5AyqUWqFHw1MlgwUtS/kwDQYJKoZIhvcNAQEL\n..."
    ],
    "certificate": "-----BEGIN CERTIFICATE-----\nnMIIDFDCCAfygAwIBAgIUXgxy54mKooz5soqQoRINazH/3pQwDQYJKoZIhvcNAQEL...",
    "revocation_time": 0
  }
}
```

<a name="read-ca-certificate-chain"></a>

### Read default issuer certificate chain

This endpoint retrieves the default issuer's CA certificate chain, including
the default issuer.

To read [other issuers' chains](#read-issuer-certificate), use the
`/pki/issuer/:issuer_ref/json` endpoint instead.

These are unauthenticated endpoints.

| Method | Path                 | Issuer    | Format                                                                            |
| :----- | :------------------- | :-------- |:----------------------------------------------------------------------------------|
| `GET`  | `/pki/ca_chain`      | `default` | PEM [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") |
| `GET`  | `/pki/cert/ca_chain` | `default` | JSON                                                                              |

~> **Note**: As of Vault 1.11.0, these endpoints now return the full chain
   (including the default issuer's certificate and all parent issuers known
   to Vault) in these responses.

#### Sample request

```shell-session
$ curl \
    http://127.0.0.1:8200/v1/pki/ca_chain
```

#### Sample response

```text
<PEM-encoded certificate chain>
```

<a name="read-crl"></a>

### Read issuer CRL

This endpoint retrieves the specified issuer's CRL.

Note that the response differs between the older `/pki/cert/crl` path and
the newer `/pki/issuer/:issuer_ref/crl` path; the latter correctly places the
PEM-encoded CRL in the `crl` field whereas the former incorrectly places it
in the `certificate` field.

Endpoints with type `complete` are full CRLs containing all revoked
certificates (as of the time of generation. Endpoints with type `delta`
contain incremental CRLs on top of the last complete CRL, with any new
certificates that have been revoked. See the [revocation configuration
section](#set-crl-configuration) for more information about these options.
The delta CRL clears when the next complete CRL is rebuilt. Consumers of
delta CRLs will need to update their client to support fetching the
corresponding full CRL when it has been regenerated; otherwise, some serial
numbers may not appear in the local copy of the full CRL if the remote
complete and delta CRLs has been regenerated.

Endpoints with source `local` only include cluster-local revocations. When
the `unified_crl` parameters is enabled in the [CRL
configuration](#set-crl-configuration), endpoints with source `unified`
will have revocations from all clusters. Generally use of the `unified`
source is more consistent with expectations of external apps, but see
the [PKI Considerations](/vault/docs/secrets/pki/considerations) page
for a discussion on cluster size and unified CRLs/OCSP.

<EnterpriseAlert product="vault">
  Unified CRLs require a Vault Enterprise license or HCP Plus cluster.
</EnterpriseAlert>

These are unauthenticated endpoints.

~> **Note**: As of Vault 1.11.0, these endpoints now serve a [version 2](https://datatracker.ietf.org/doc/html/rfc5280#section-5.1.2.1) CRL response.

~> Note: this endpoint accepts the `If-Modified-Since` header, to respond with
   304 Not Modified when the requested resource has not changed. This header
   needs to be allowed on the PKI mount by tuning the `passthrough_request_headers`
   option. In order for clients to know the last modified time, the response
   header `Last-Modified` needs to be added to the mount tunable
   `allowed_response_headers`.

| Method | Path                                            | Issuer    | Format                                                                            | Type     | Source  |
| :----- | :---------------------------------------------- | :-------- | :-------------------------------------------------------------------------------- | :------- | :------ |
| `GET`  | `/pki/cert/crl`                                 | `default` | JSON                                                                              | Complete | Local   |
| `GET`  | `/pki/crl`                                      | `default` | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Complete | Local   |
| `GET`  | `/pki/crl/pem`                                  | `default` | PEM [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Complete | Local   |
| `GET`  | `/pki/cert/delta-crl`                           | `default` | JSON                                                                              | Delta    | Local   |
| `GET`  | `/pki/crl/delta`                                | `default` | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Delta    | Local   |
| `GET`  | `/pki/crl/delta/pem`                            | `default` | PEM [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Delta    | Local   |
| `GET`  | `/pki/issuer/:issuer_ref/crl`                   | Selected  | JSON                                                                              | Complete | Local   |
| `GET`  | `/pki/issuer/:issuer_ref/crl/der`               | Selected  | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Complete | Local   |
| `GET`  | `/pki/issuer/:issuer_ref/crl/pem`               | Selected  | PEM [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Complete | Local   |
| `GET`  | `/pki/issuer/:issuer_ref/crl/delta`             | Selected  | JSON                                                                              | Delta    | Local   |
| `GET`  | `/pki/issuer/:issuer_ref/crl/delta/der`         | Selected  | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Delta    | Local   |
| `GET`  | `/pki/issuer/:issuer_ref/crl/delta/pem`         | Selected  | PEM [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Delta    | Local   |
| `GET`  | `/pki/cert/unified-crl`                         | `default` | JSON                                                                              | Complete | Unified |
| `GET`  | `/pki/unified-crl`                              | `default` | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Complete | Unified |
| `GET`  | `/pki/unified-crl/pem`                          | `default` | PEM [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Complete | Unified |
| `GET`  | `/pki/cert/unified-delta-crl`                   | `default` | JSON                                                                              | Delta    | Unified |
| `GET`  | `/pki/unified-crl/delta`                        | `default` | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Delta    | Unified |
| `GET`  | `/pki/unified-crl/delta/pem`                    | `default` | PEM [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Delta    | Unified |
| `GET`  | `/pki/issuer/:issuer_ref/unified-crl`           | Selected  | JSON                                                                              | Complete | Unified |
| `GET`  | `/pki/issuer/:issuer_ref/unified-crl/der`       | Selected  | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Complete | Unified |
| `GET`  | `/pki/issuer/:issuer_ref/unified-crl/pem`       | Selected  | PEM [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Complete | Unified |
| `GET`  | `/pki/issuer/:issuer_ref/unified-crl/delta`     | Selected  | JSON                                                                              | Delta    | Unified |
| `GET`  | `/pki/issuer/:issuer_ref/unified-crl/delta/der` | Selected  | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Delta    | Unified |
| `GET`  | `/pki/issuer/:issuer_ref/unified-crl/delta/pem` | Selected  | PEM [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Delta    | Unified |

#### Parameters

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.

~> Note: This parameter is not present on the `/pki/cert/crl` and
   `/pki/crl(/pem)?` paths and takes the implicit value `default`.

#### Sample request

```shell-session
$ curl \
    http://127.0.0.1:8200/v1/pki/issuer/root-x1/crl
```

#### Sample response

```json
{
  "data": {
    "crl": "-----BEGIN X509 CRL-----\nMIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB3Jvb3QgeDEXDTIy\n..."
  }
}
```

### OCSP request

This endpoint retrieves an OCSP response (revocation status) for a given serial number. The request/response formats are
based on [RFC 6960](https://datatracker.ietf.org/doc/html/rfc6960)

Endpoints with source `local` only include cluster-local revocations. When
the `unified_crl` parameters is enabled in the [CRL
configuration](#set-crl-configuration), endpoints with source `unified`
will have revocations from all clusters. Generally use of the `unified`
source is more consistent with expectations of external apps, but see
the [PKI Considerations](/vault/docs/secrets/pki/considerations) page
for a discussion on cluster size and unified CRLs/OCSP.

<EnterpriseAlert product="vault">
  Unified OCSP requires a Vault Enterprise license or HCP Plus cluster.
</EnterpriseAlert>

At this time there are certain limitations of the OCSP implementation at this path:

 1. Only a single serial number within the request will appear in the response,
 1. None of the extensions defined in the RFC are supported for requests or responses,
 1. Ed25519 backed CA's are not supported for OCSP requests,
 1. Note that this API will not work with the Vault client as both request and responses are DER encoded, and
 1. Note that KMS based issuers which require PSS support are not supported either (such as PKCS#11 HSMs or GCP in certain scenarios).

These are unauthenticated endpoints.

| Method | Path                                                       | Response Format                                                                   | Source  |
| :----- | :--------------------------------------------------------- | :-------------------------------------------------------------------------------- | :------ |
| `GET`  | `/pki/ocsp/<base 64+URL encoded ocsp DER request>`         | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Local   |
| `POST` | `/pki/ocsp`                                                | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Local   |
| `GET`  | `/pki/unified-ocsp/<base 64+URL encoded ocsp DER request>` | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Unified |
| `POST` | `/pki/unified-ocsp`                                        | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") | Unified |

#### Parameters

 - None

#### Sample request

```shell-session
openssl ocsp -no_nonce -issuer issuer.pem -CAfile ca_chain.pem -cert cert-to-revoke.pem -text -url $VAULT_ADDR/v1/pki/ocsp
```

### List certificates

This endpoint returns a list of the current certificates by serial number only.
The response does not include the [special serial numbers](#read-certificate-serial-param-values)
(`ca`, `ca_chain`, and `crl`) that can be used with `/pki/cert/:serial`.

This includes only certificates issued by this mount with `no_store=false`.
While root generation does create entries here, importing certificates
(including both roots and intermediates) will not cause the imported
certificate's serial number to appear in this list.

~> Note: The endpoint to list all certificates is authenticated. This is to
   prevent automated enumeration of issued certificates for internal services;
   however, this information should generally be considered non-sensitive and
   the certificates themselves are exposed without authentication (provided
   their serial number is known).<br /><br />
   Many Public CAs participate in the Certificate Transparency initiative,
   where all issued certificates are publicly disclosed in the interest
   of third-party verification of CA integrity.

| Method | Path         |
| :----- | :----------- |
| `LIST` | `/pki/certs` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request LIST \
    http://127.0.0.1:8200/v1/pki/certs
```

#### Sample response

```json
{
  "data": {
    "keys": [
      "17:67:16:b0:b9:45:58:c0:3a:29:e3:cb:d6:98:33:7a:a6:3b:66:c1",
      "26:0f:76:93:73:cb:3f:a0:7a:ff:97:85:42:48:3a:aa:e5:96:03:21"
    ]
  }
}
```

<a name="read-raw-certificate"></a>

### Read certificate

This endpoint retrieves the certificate specified by its serial number,
including issued certificates.

~> Note: With the exception of the special values (`ca`, `crl`, and
   `ca_chain`), `/pki/cert/:serial` will return different results on
   different clusters. This is because stored certificates are not
   replicated across different Performance Replication clusters.

These are unauthenticated endpoints.

| Method | Path                        | Format                                                                            |
| :----- | :-------------------------- |:----------------------------------------------------------------------------------|
| `GET`  | `/pki/cert/:serial`         | JSON                                                                              |
| `GET`  | `/pki/cert/:serial/raw`     | DER [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") |
| `GET`  | `/pki/cert/:serial/raw/pem` | PEM [\[1\]](#vault-cli-with-der-pem-responses "Vault CLI With DER/PEM Responses") |

#### Parameters

- `serial` `(string: <required>)` - Specifies the serial of the key to read.
  This is part of the request URL. Valid values for `serial` are:

<a name="read-certificate-serial-param-values"></a>

  - `<serial>` for the certificate with the given serial number, in hyphen-separated or colon-separated hexadecimal.
  - `ca` for the _default_ issuer's CA certificate
  - `crl` for the _default_ issuer's CRL
  - `ca_chain` for the _default_ issuer's CA trust chain.

~> **Note**: As of Vault 1.11.0, these endpoints return the full chain
   (including this certificate and all parent issuers known to Vault) in
   the `ca_chain` response, for both the `certificate` and newer `ca_chain`
   fields. The root certificate is no longer elided.

#### Sample request

```shell-session
$ curl \
    http://127.0.0.1:8200/v1/pki/cert/67:b4:f7:2c:aa:ef:b9:30:f6:ae:f5:12:21:79:ac:08:8a:86:89:72
```

#### Sample response

```json
{
  "data": {
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIGmDCCBYCgAwIBAgIHBzEB3fTzhTANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UE\n...",
    "revocation_time": 1667400107,
    "revocation_time_rfc3339": "2022-11-02T14:41:47.327515Z",
    "issuer_id": "e27bf456-51e1-d937-0001-4a609184fd9b"
  }
}
```

---

## Managing keys and issuers

The following endpoints are highly privileged and allow operators to generate
or import new issuer certificates and keys, remove existing keys and issuers,
or read internal information about keys and issuers.

### List issuers

Refer to the [earlier section](#list-issuers) for more information about
listing issuers.

### List keys

This endpoint returns a list of keys currently provisioned in this mount.
The response includes both the key's identifier as well as the name chosen
by the operators; either can be used to refer to the key later.

This endpoint is authenticated.

| Method | Path         |
| :----- | :----------- |
| `LIST` | `/pki/keys`  |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request LIST \
    http://127.0.0.1:8200/v1/pki/keys
```

#### Sample response

```json
{
  "data": {
    "key_info": {
      "f9244f54-adc7-4a5c-6b08-6ca3a3325620": {
        "key_name": "imported-root-key"
      },
    },
    "keys": [
      "f9244f54-adc7-4a5c-6b08-6ca3a3325620",
    ]
  }
}
```

### Generate key

This endpoint generates a new private key for use in the PKI mount. This key
can be used with either the [root](#generate-root) or [intermediate](#generate-intermediate-csr)
endpoints, using the `type=existing` variant.

If the path ends with `exported`, the private key will be returned in the
response; if it is `internal` the private key will not be returned and _cannot
be retrieved later_; if it is `kms`, a [managed keys](#managed-keys) will be
used.

| Method | Path                               |
| :----- | :--------------------------------- |
| `POST` | `/pki/keys/generate/:type`         |

#### Parameters

- `type` `(string: <required>)` - Specifies the type of the key to
  create. If `exported`, the private key will be returned in the response; if
  `internal` the private key will not be returned and _cannot be retrieved
  later_; `kms` is also supported: [see below for more details about managed
  keys](#managed-keys). This parameter is part of the request URL.

- `key_name` `(string: "")` - When a new key is created with this request,
  optionally specifies the name for this. The global ref `default` may not
  be used as a name.

- `key_type` `(string: "rsa")` - Specifies the desired key type; must be `rsa`, `ed25519`
  or `ec`.

~> **Note**: In FIPS 140-2 mode, the following algorithms are not certified
   and thus should not be used: `ed25519`.

- `key_bits` `(int: 0)` - Specifies the number of bits to use for the
  generated keys. Allowed values are 0 (universal default); with
  `key_type=rsa`, allowed values are: 2048 (default), 3072, or
  4096; with `key_type=ec`, allowed values are: 224, 256 (default),
  384, or 521; ignored with `key_type=ed25519`.

#### Managed keys parameters

See [Managed Keys](#managed-keys) for additional details on this feature, if
`type` was set to `kms`. One of the following parameters must be set

- `managed_key_name` `(string: "")` - The managed key's configured name.

- `managed_key_id` `(string: "")` - The managed key's UUID.

#### Sample payload

```json
{
  "key_type": "ec",
  "key_bits": "256",
  "key_name": "root-key-2022"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/keys/generate/internal
```

#### Sample response

```json
{
  "request_id": "8ad22b2f-7d14-f2cd-a10a-d1abc33676ab",
  "lease_id": "",
  "lease_duration": 0,
  "renewable": false,
  "data": {
    "key_id": "adda2443-a8aa-d181-9d07-07c7be6a76ab",
    "key_name": "root-key-2022",
    "key_type": "ec"
  },
  "warnings": null
}
```

### Generate root

This endpoint generates a new self-signed CA certificate and private key. If
the path ends with `exported`, the private key will be returned in the
response; if it is `internal` the private key will not be returned and _cannot
be retrieved later_; if it is `existing`, the key specified by `key_ref` will
be reused for this root; if it is `kms`, a [managed keys](#managed-keys) will
be used.

This generated root will sign its own CRL. Authority Access distribution points
use the values set via `config/urls`.

~> **Note**: As of Vault 1.11.0, the PKI Secrets Engine now supports multiple
   issuers under a single mount. Use the management operations in this section
   to [list](#list-issuers) and [modify issuers](#update-issuer) within this
   mount. No issuers will be overridden by calling this operation. Deleting
   individual keys and issuers should be preferred to calling `DELETE /pki/root`,
   [which deletes everything](#delete-all-issuers-and-keys).

| Method | Path                               |
| :----- | :--------------------------------- |
| `POST` | `/pki/root/generate/:type`         |
| `POST` | `/pki/issuers/generate/root/:type` |
| `POST` | `/pki/root/rotate/:type`           |

#### Parameters

- `type` `(string: <required>)` - Specifies the type of the root to
  create. If `exported`, the private key will be returned in the response; if
  `internal` the private key will not be returned and _cannot be retrieved
  later_; if `existing`, we use the value of the `key_ref` parameter to find
  existing key material to create the CSR; `kms` is also supported: [see below
  for more details about managed keys](#managed-keys). This parameter is part
  of the request URL.

- `issuer_name` `(string: "")` - Provides a name to the specified issuer. The
  name must be unique across all issuers and not be the reserved value
  `default`. When no value is supplied and the path is `/pki/root/rotate/:type`,
  the default value of `"next"` will be used.

- `key_name` `(string: "")` - When a new key is created with this request,
  optionally specifies the name for this. The global ref `default` may not
  be used as a name.

- `key_ref` `(string: "default")` - Specifies the key (either `default`, by
  name, or by identifier) to use for generating this request. Only suitable
  for `type=existing` requests.

- `common_name` `(string: <required>)` - Specifies the requested CN for the
  certificate. If more than one `common_name` is desired, specify the
  alternative names in the `alt_names` list.

- `alt_names` `(string: "")` - Specifies the requested Subject Alternative
  Names, in a comma-delimited list. These can be host names or email addresses;
  they will be parsed into their respective fields.

- `ip_sans` `(string: "")` - Specifies the requested IP Subject Alternative
  Names, in a comma-delimited list.

- `uri_sans` `(string: "")` - Specifies the requested URI Subject Alternative
  Names, in a comma-delimited list.

- `other_sans` `(string: "")` - Specifies custom OID/UTF8-string SANs. These
  must match values specified on the role in `allowed_other_sans` (see role
  creation for allowed_other_sans globbing rules).
  The format is the same as OpenSSL: `<oid>;<type>:<value>` where the
  only current valid type is `UTF8`. This can be a comma-delimited list or a
  JSON string slice.

- `ttl` `(string: "")` - Specifies the requested Time To Live (after which the
  certificate will be expired). This cannot be larger than the engine's max (or,
  if not set, the system max). See `not_after` as an alternative for setting an
  absolute end date (rather than a relative one).

- `format` `(string: "pem")` - Specifies the format for returned data. Can be
  `pem`, `der`, or `pem_bundle`. If `der`, the output is base64 encoded. If
  `pem_bundle`, the `certificate` field will contain the private key (if
  exported) and certificate, concatenated; if the issuing CA is not a
  Vault-derived self-signed root, this will be included as well.

- `private_key_format` `(string: "der")` - Specifies the format for marshaling
  the private key within the private_key response field. Defaults to `der` which will
  return either base64-encoded DER or PEM-encoded DER, depending on the value of
  `format`. The other option is `pkcs8` which will return the key marshalled as
  PEM-encoded PKCS8.

~> **Note** that this does not apply to the private key within the certificate
  field if `format=pem_bundle` parameter is specified.

- `key_type` `(string: "rsa")` - Specifies the desired key type; must be `rsa`, `ed25519`
  or `ec`.

~> **Note**: In FIPS 140-2 mode, the following algorithms are not certified
   and thus should not be used: `ed25519`.

- `key_bits` `(int: 0)` - Specifies the number of bits to use for the
  generated keys. Allowed values are 0 (universal default); with
  `key_type=rsa`, allowed values are: 2048 (default), 3072, or
  4096; with `key_type=ec`, allowed values are: 224, 256 (default),
  384, or 521; ignored with `key_type=ed25519`.

- `max_path_length` `(int: -1)` - Specifies the maximum path length to encode in
  the generated certificate. `-1` means no limit. Unless the signing certificate
  has a maximum path length set, in which case the path length is set to one
  less than that of the signing certificate. A limit of `0` means a literal
  path length of zero.

- `exclude_cn_from_sans` `(bool: false)` - If true, the given `common_name` will
  not be included in DNS or Email Subject Alternate Names (as appropriate).
  Useful if the CN is not a hostname or email address, but is instead some
  human-readable identifier.

- `permitted_dns_domains` `(string: "")` - A comma separated string (or, string
  array) containing DNS domains for which certificates are allowed to be issued
  or signed by this CA certificate. Note that subdomains are allowed, as per
  [RFC 5280 Section 4.2.1.10 - Name
  Constraints](https://tools.ietf.org/html/rfc5280#section-4.2.1.10).

- `ou` `(string: "")` - Specifies the OU (OrganizationalUnit) values in the
  subject field of the resulting certificate. This is a comma-separated string
  or JSON array.

- `organization` `(string: "")` - Specifies the O (Organization) values in the
  subject field of the resulting certificate. This is a comma-separated string
  or JSON array.

- `country` `(string: "")` - Specifies the C (Country) values in the subject
  field of the resulting certificate. This is a comma-separated string or JSON
  array.

- `locality` `(string: "")` - Specifies the L (Locality) values in the subject
  field of the resulting certificate. This is a comma-separated string or JSON
  array.

- `province` `(string: "")` - Specifies the ST (Province) values in the subject
  field of the resulting certificate. This is a comma-separated string or JSON
  array.

- `street_address` `(string: "")` - Specifies the Street Address values in the
  subject field of the resulting certificate. This is a comma-separated string
  or JSON array.

- `postal_code` `(string: "")` - Specifies the Postal Code values in the
  subject field of the resulting certificate. This is a comma-separated string
  or JSON array.

- `serial_number` `(string: "")` -  - Specifies the default Subject's named
  [Serial Number](https://datatracker.ietf.org/doc/html/rfc4519#section-2.31)
  value, if any. If you want more than one, specify alternative names in the
  `alt_names` map using OID 2.5.4.5. Note that this has no impact on the
  Certificate's serial number field, which Vault randomly generates.

- `not_before_duration` `(duration: "30s")` - Specifies the duration by which to
  backdate the NotBefore property. This value has no impact in the validity period
  of the requested certificate, specified in the `ttl` field.
  Uses [duration format strings](/vault/docs/concepts/duration-format).

- `not_after` `(string)` - Set the Not After field of the certificate with
  specified date value. The value format should be given in UTC format
  `YYYY-MM-ddTHH:MM:SSZ`. Supports the Y10K end date for IEEE 802.1AR-2018
  standard devices, `9999-12-31T23:59:59Z`.

* ~> Note: Keys of type `rsa` currently only support PKCS#1 v1.5 signatures.

#### Managed keys parameters

See [Managed Keys](#managed-keys) for additional details on this feature, if
`type` was set to `kms`. One of the following parameters must be set

- `managed_key_name` `(string: "")` - The managed key's configured name.

- `managed_key_id` `(string: "")` - The managed key's UUID.

#### Sample payload

```json
{
  "common_name": "example.com"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/root/generate/internal
```

#### Sample response

```json
{
  "lease_id": "",
  "lease_duration": 0,
  "renewable": false,
  "data": {
    "expiration": "1654105687",
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE-----\n",
    "issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE-----\n",
    "serial_number": "39:dd:2e:90:b7:23:1f:8d:d3:7d:31:c5:1b:da:84:d0:5b:65:31:58",
    "issuer_id": "7b493f17-6c08-ff73-cf1a-99bfcc448a73",
    "issuer_name": "",
    "key_id": "22b82e37-529d-7251-7d78-3862bfd069ac",
    "key_name": ""
  },
  "auth": null
}
```

<a name="generate-intermediate"></a>

### Generate intermediate CSR

This endpoint returns a new CSR for signing, optionally generating a new private
key. If using Vault as a root (and, like many other CAs), the various parameters
on the final signed certificate are set at signing time and _may or may not honor
the parameters set here_ (and transmitted in the returned CSR).

Note that this API supports [Managed Keys](/vault/docs/enterprise/managed-keys);
additional details are available [below in a dedicated section](#managed-keys).

The parameters below are mostly meant as a helper function; not all possible
parameters that can be set in a CSR are supported in this request.

No new issuer is yet created by this call; note that a new key may be
generated depending on the `type` request parameter.

~> **Note**: In order to complete the intermediate generation, the CSR must be
   signed and the resulting certificate imported. This may involve working with
   external systems (such as an external or offline root CA) to transmit the
   CSR and complete the signing before the signed intermediate certificate is
   [imported](#import-ca-certificate-and-keys) into this mount.

| Method | Path                                       | Private key source (`type`) |
| :----- |:-------------------------------------------| :-------------------------- |
| `POST` | `/pki/intermediate/generate/:type`         | specified per request       |
| `POST` | `/pki/issuers/generate/intermediate/:type` | specified per request       |
| `POST` | `/pki/intermediate/cross-sign`             | `existing`                  |

#### Parameters

- `type` `(string: <required>)` - Specifies the type of the intermediate to
  create. If `exported`, the private key will be returned in the response; if
  `internal` the private key will not be returned and _cannot be retrieved
  later_; if `existing`, we expect the `key_ref` parameter to use existing
  key material to create the CSR; `kms` is also supported: [see below for more
  details](#managed-keys). This parameter is part of the request URL.

- `common_name` `(string: <required>)` - Specifies the requested CN for the
  certificate. If more than one `common_name` is desired, specify the
  alternative names in the `alt_names` list.

- `alt_names` `(string: "")` - Specifies the requested Subject Alternative
  Names, in a comma-delimited list. These can be host names or email addresses;
  they will be parsed into their respective fields.

- `ip_sans` `(string: "")` - Specifies the requested IP Subject Alternative
  Names, in a comma-delimited list.

- `uri_sans` `(string: "")` - Specifies the requested URI Subject Alternative
  Names, in a comma-delimited list.

- `other_sans` `(string: "")` - Specifies custom OID/UTF8-string SANs. These
  must match values specified on the role in `allowed_other_sans` (see role
  creation for allowed_other_sans globbing rules).
  The format is the same as OpenSSL: `<oid>;<type>:<value>` where the
  only current valid type is `UTF8`. This can be a comma-delimited list or a
  JSON string slice.

- `format` `(string: "pem")` - Specifies the format for returned data. This can be
  `pem`, `der`, or `pem_bundle`; defaults to `pem`. If `der`, the output is
  base64 encoded. If `pem_bundle`, the `csr` field will contain the private key
  (if exported) and CSR, concatenated.

- `private_key_format` `(string: "der")` - Specifies the format for marshaling
  the private key within the private_key response field. Defaults to `der` which will
  return either base64-encoded DER or PEM-encoded DER, depending on the value of
  `format`. The other option is `pkcs8` which will return the key marshalled as
  PEM-encoded PKCS8.

~> **Note** that this does not apply to the private key within the certificate
  field if `format=pem_bundle` parameter is specified.

- `key_type` `(string: "rsa")` - Specifies the desired key type; must be `rsa`, `ed25519`
  or `ec`. Not suitable for `type=existing` requests.

~> **Note**: In FIPS 140-2 mode, the following algorithms are not certified
   and thus should not be used: `ed25519`.

~> **Note**: Keys of type `rsa` currently only support PKCS#1 v1.5 signatures.
   This includes any managed keys.

- `key_bits` `(int: 0)` - Specifies the number of bits to use for the
  generated keys. Allowed values are 0 (universal default); with
  `key_type=rsa`, allowed values are: 2048 (default), 3072, or
  4096; with `key_type=ec`, allowed values are: 224, 256 (default),
  384, or 521; ignored with `key_type=ed25519`. Not suitable for
  `type=existing` requests.

- `key_name` `(string: "")` - When a new key is created with this request,
  optionally specifies the name for this. The global ref `default` may not
  be used as a name.

- `key_ref` `(string: "default")` - Specifies the key (either `default`, by
  name, or by identifier) to use for generating this request. Only suitable
  for `type=existing` requests.

- `signature_bits` `(int: 0)` - Specifies the number of bits to use in
  the signature algorithm; accepts 256 for SHA-2-256, 384 for SHA-2-384,
  and 512 for SHA-2-512. Defaults to 0 to automatically detect based
  on issuer's key length (SHA-2-256 for RSA keys, and matching the curve size
  for NIST P-Curves).

~> **Note**: ECDSA and Ed25519 issuers do not follow configuration of the
`signature_bits` value; only RSA issuers will change signature types
based on this parameter.

- `exclude_cn_from_sans` `(bool: false)` - If true, the given `common_name` will
  not be included in DNS or Email Subject Alternate Names (as appropriate).
  Useful if the CN is not a hostname or email address, but is instead some
  human-readable identifier.

- `ou` `(string: "")` - Specifies the OU (OrganizationalUnit) values in the
  subject field of the resulting CSR. This is a comma-separated string
  or JSON array.

- `organization` `(string: "")` - Specifies the O (Organization) values in the
  subject field of the resulting CSR. This is a comma-separated string
  or JSON array.

- `country` `(string: "")` - Specifies the C (Country) values in the subject
  field of the resulting CSR. This is a comma-separated string or JSON
  array.

- `locality` `(string: "")` - Specifies the L (Locality) values in the subject
  field of the resulting CSR. This is a comma-separated string or JSON
  array.

- `province` `(string: "")` - Specifies the ST (Province) values in the subject
  field of the resulting CSR. This is a comma-separated string or JSON
  array.

- `street_address` `(string: "")` - Specifies the Street Address values in the
  subject field of the resulting CSR. This is a comma-separated string
  or JSON array.

- `postal_code` `(string: "")` - Specifies the Postal Code values in the
  subject field of the resulting CSR. This is a comma-separated string
  or JSON array.

- `serial_number` `(string: "")` - Specifies the requested Subject's named
  [Serial Number](https://datatracker.ietf.org/doc/html/rfc4519#section-2.31)
  value, if any. If you want more than one, specify alternative names in the
  `alt_names` map using OID 2.5.4.5. Note that this has no impact on the
  Certificate's serial number field, which Vault randomly generates.

- `add_basic_constraints` `(bool: false)` - Whether to add a Basic Constraints
  extension with CA: true. Only needed as a workaround in some compatibility
  scenarios with Active Directory Certificate Services.

#### Managed keys parameters

See [Managed Keys](#managed-keys) for additional details on this feature, if
`type` was set to `kms`. One of the following parameters must be set

- `managed_key_name` `(string: "")` - The managed key's configured name.

- `managed_key_id` `(string: "")` - The managed key's UUID.

#### Sample payload

```json
{
  "common_name": "www.example.com"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/intermediate/generate/exported
```

```json
{
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE REQUEST-----\n",
    "private_key": "-----BEGIN RSA PRIVATE KEY-----\\nMIIEpAIBAAKCAQEAwsANtGz9gS3o5SwTSlOG1l-----END RSA PRIVATE KEY-----",
    "private_key_type": "rsa"
  },
  "warnings": null,
  "auth": null
}
```


<a name="submit-ca-information"></a>
<a name="set-signed-intermediate"></a>

### Import CA certificates and keys

This endpoint allows submitting (importing) the CA information for the backend
via a PEM file containing the CA certificate and any private keys, concatenated
together, in any order.

Each certificate will be validated to ensure it is a valid CA (has an asserted
isCA basic constraint); non-CA certs will err. Any provided CRLs will be
ignored. Each unique certificate and private key will be imported as its own
issuer or key entry; duplicates (including with existing keys) will be ignored.

The response will indicate what issuers and keys were created as part of this
request (in the `imported_issuers` and `imported_keys`), along with a `mapping`
field, indicating which keys belong to which issuers (including from already
imported entries present in the same bundle). In Vault 1.14.0, the response
also contains an `existing_issuers` and `existing_keys` fields, which specifies
the issuer and key IDs of any entries in the bundle that already
existed within this mount.

| Method | Path                           | Allows private keys | Request Parameter |
| :----- | :----------------------------- | :------------------ | :---------------- |
| `POST` | `/pki/config/ca`               | yes                 | `pem_bundle`      |
| `POST` | `/pki/issuers/import/bundle`   | yes                 | `pem_bundle`      |
| `POST` | `/pki/issuers/import/cert`     | no                  | `pem_bundle`      |
| `POST` | `/pki/intermediate/set-signed` | no                  | `certificate`     |

~> **Note**: endpoints which allow importing private keys _should_ be considered
   highly privileged and restricted appropriately. Endpoints which allow
   importing issuers should also be restricted, but note that issuers without
   keys are unable to issue certificates or CRLs.

~> Note: Vault will deduplicate differently-encoded but same-valued keys and
   issuers. This means the returned certificate _may_ differ in encoding from
   the one provided on subsequent re-imports of the same issuer or key.

~> Note: This import may fail due to CRL rebuilding issues or other potential
   issues; this may impact long-term use of these issuers, but some issuers or
   keys may still be imported as a result of this process.

~> Warning: See the [note](/vault/docs/secrets/pki/considerations#issuer-subjects-and-crls)
   regarding Subject naming on externally created CA certificates and
   shortcomings with CRL building.

#### Parameters

- `pem_bundle` `(string: <required>)` - Specifies the unencrypted private key
  and certificate, concatenated in PEM format.

~> Note: this parameter is on the `/pki/config/ca` and `/pki/issuers/import/*`
   paths; it is not on the `/pki/intermediate/set-signed` path.

- `certificate` `(string: <required>)` - Specifies the certificates to import,
  concatenated in PEM format.

~> Note: this parameter is **only** on the `/pki/intermediate/set-signed` path.

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data "@payload.json" \
    http://127.0.0.1:8200/v1/pki/config/ca
```

Note that if you provide the data through the HTTP API, it must be
JSON-formatted, with newlines replaced with `\n`, like so:

```json
{
  "pem_bundle": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END CERTIFICATE-----"
}
```

#### Sample response

```json
{
  "data": {
    "imported_issuers": ["1ae8ce9d-2f70-0761-a465-8c9840a247a2"],
    "imported_keys": ["97be2525-717a-e2f7-88da-0a20e11aad88"],
    "mapping": {
      "1ae8ce9d-2f70-0761-a465-8c9840a247a2": "97be2525-717a-e2f7-88da-0a20e11aad88"
    },
    "existing_issuers": [],
    "existing_keys": []
  }
}
```

### Read issuer

This endpoint allows an operator to fetch a single issuer certificate and its
chain, including internal information not exposed on the [unauthenticated
`/pki/issuer/:issuer_ref/json`](#read-issuer-certificate) endpoint. This
includes information about the name, the key material, if an explicitly
constructed chain has been set, what the behavior is for signing longer TTL'd
certificates, and what usage modes are set on this issuer.

| Method | Path                      |
| :----- | :------------------------ |
| `GET`  | `/pki/issuer/:issuer_ref` |

#### Parameters

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/issuer/default
```

#### Sample response

```text
{
  "data": {
    "ca_chain": [
      "-----BEGIN CERTIFICATE-----\nMIIDFDCCAfygAwIBAgIUXgxy54mKooz5soqQoRINazH/3pQwDQYJKoZIhvcNAQEL\n...",
      "-----BEGIN CERTIFICATE-----\nMIIDFTCCAf2gAwIBAgIUUo/qwLm5AyqUWqFHw1MlgwUtS/kwDQYJKoZIhvcNAQEL\n..."
    ],
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIDFDCCAfygAwIBAgIUXgxy54mKooz5soqQoRINazH/3pQwDQYJKoZIhvcNAQEL\n...",
    "issuer_id": "7545992c-1910-0898-9e64-d575549fbe9c",
    "issuer_name": "root-x1",
    "key_id": "baadd98d-ec5a-66ac-06b7-dfc91c02c9cf",
    "leaf_not_after_behavior": "truncate",
    "manual_chain": null,
    "usage": "read-only,issuing-certificates,crl-signing,ocsp-signing"
  }
}
```

### Update issuer

This endpoint allows an operator to manage a single issuer, updating various
properties about it, including its name, an explicitly constructed chain,
what the behavior is for signing longer TTL'd certificates, and what usage
modes are set on this issuer.

Note that it is not possible to change the certificate of this issuer; to
do so, import a new issuer and a new `issuer_id` will be assigned.

| Method  | Path                      |
| :------ | :------------------------ |
| `POST`  | `/pki/issuer/:issuer_ref` |
| `PATCH` | `/pki/issuer/:issuer_ref` |

~> **Note** `POST`ing to this endpoint causes Vault to overwrite the previous
   contents of the issuer, using the provided request data (and any defaults
   for elided parameters). It does not update only the provided fields.<br /><br />
   Since Vault 1.11.0, Vault supports the PATCH operation to this endpoint,
   using the [JSON patch format](https://datatracker.ietf.org/doc/html/rfc6902)
   supported by KVv2, allowing update of specific fields. Note that
   `vault write` uses `POST`.

#### Parameters

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.

- `issuer_name` `(string: "")` - Provides a name to the specified issuer. The
  name must be unique across all issuers and not be the reserved value
  `default`.

- `leaf_not_after_behavior` `(string: "err")` - Behavior of a leaf's
  `NotAfter` field during issuance. Valid options are:

  - `err`, to error if the computed `NotAfter` exceeds that of this issuer;
  - `truncate` to silently truncate the requested `NotAfter` value to that
    of this issuer; or
  - `permit` to allow this issuance to succeed with a `NotAfter` value
    exceeding that of this issuer.

~> Note: Not all values result in leaf certificates that can be validated
   through the entire validity period. It is suggested to use `truncate` for
   intermediate CAs and `permit` only for root CAs. This is because
   (root) certificates in browsers' trust stores typically aren't checked
   for validity, whereas intermediate CA certificates sent in TLS connections
   are checked for validity at the time of use. This means that a leaf
   certificate permitted to be issued for longer than the intermediate likely
   won't continue to validate after the intermediate has expired.

- `manual_chain` `([]string: nil)` - Chain of issuer references to build this
  issuer's computed CAChain field from, when non-empty.

~> Note: the `manual_chain` field is an advanced field useful when automatic
   chain building isn't desired. The first element _must_ be the present
   issuer's reference. Subsequent references _should_ validate previous
   entries, terminating with a root certificate. _Ideally_ a single linear
   chain would come first (from this issuer to a single root certificate)
   before any parallel, alternate chains appear.<br /><br />
   This field is especially useful for cross-signed intermediates within
   Vault. Because each cross-signed intermediate will only know of the
   one root, but issuance should serve both, update the issuers' entries
   with the desired `manual_chain` value.<br /><br />
   The CA Chain returned by a GET to the issuer configuration is the same
   chain presented during signing and (if this issuer is the default) on
   the `/ca_chain` path. Setting `manual_chain` thus allows controlling
   the presented chain as desired.

- `usage` `([]string: read-only,issuing-certificates,crl-signing,ocsp-signing)` - Allowed
  usages for this issuer. Valid options are:

  - `read-only`, to allow this issuer to be read; implict; always allowed;
  - `issuing-certificates`, to allow this issuer to be used for issuing other
    certificates; or
  - `crl-signing`, to allow this issuer to be used for signing CRLs. This is
    separate from the CRLSign KeyUsage on the x509 certificate, but this usage
    cannot be set unless that KeyUsage is allowed on the x509 certificate.
  - `ocsp-signing`, to allow this issuer to be used for signing OCSP responses

~> Note: The `usage` field allows for a soft-delete capability on the issuer,
   or to prevent use of the issuer prior to it being enabled. For example,
   as issuance is rotated to a new issuer, the old issuer could be marked
   `usage=read-only,crl-signing,ocsp-signing`, allowing existing certificates to be revoked
   (and the CRL updated), but preventing new certificate issuance. After all
   certificates issued under this certificate have expired, this certificate
   could be marked `usage=read-only`, freezing the CRL. Finally, after a grace
   period, the issuer could be deleted.

- `revocation_signature_algorithm` `(string: "")` - Which signature algorithm
  to use when building CRLs. See Go's [`x509.SignatureAlgorithm`](https://pkg.go.dev/crypto/x509#SignatureAlgorithm)
  constant for possible values. This flag allows control over hash function
  and signature scheme (PKCS#1v1.5 vs PSS). The default (empty string) value
  is for Go to select the signature algorithm automatically, which may not
  always work.

~> Note: This can fail if the underlying key does not support the requested
   signature algorithm; this may not always be known at modification time.
   This most commonly needs to be modified when using PKCS#11 managed keys
   with the `CKM_RSA_PKCS_PSS` mechanism type.

- `issuing_certificates` `(array<string>: nil)` - Specifies the URL values for
  the Issuing Certificate field. This can be an array or a comma-separated
  string list. See also [RFC 5280 Section 4.2.2.1](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.2.1)
  for information about the Authority Information Access field.

- `crl_distribution_points` `(array<string>: nil)` - Specifies the URL values
  for the CRL Distribution Points field. This can be an array or a
  comma-separated string list. See also [RFC 5280 Section 4.2.1.13](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.13)
  for information about the CRL Distribution Points field.

~> Note: When multiple Performance Replication clusters are enabled, each
   cluster will have its own CRL. Additionally, when multiple issuers are
   in use under a single mount, each issuer will also have its own CRL
   distribution point. These separate CRLs should either be aggregated into a
   single CRL (externally; as Vault does not support this functionality)
   or multiple `crl_distribution_points` should be specified here, pointing
   to each cluster and issuer.

- `ocsp_servers` `(array<string>: nil)` - Specifies the URL values for the OCSP
  Servers field. This can be an array or a comma-separated string list. See also
  [RFC 5280 Section 4.2.2.1](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.2.1)
  for information about the Authority Information Access field.

- `enable_aia_url_templating` `(bool: false)` - Specifies that the above AIA
  URL values (`issuing_certificates`, `crl_distribution_points`, and
  `ocsp_servers`) should be templated. This replaces the literal value
  `{{issuer_id}}` with the ID of the issuer doing the issuance, the
  literal value `{{cluster_path}}` with the value of `path` from the
  cluster-local configuration endpoint `/config/cluster`, and the
  literal value `{{cluster_aia_path}}` with the value of `aia_path` from
  the cluster-local configuration endpoint `/config/cluster`.

~> **Note**: If no cluster-local address is present and templating is used,
   issuance will fail.

#### Sample payload

```json
{
  "issuer_name": "root-x1"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/issuer/default
```

#### Sample response

```text
{
  "data": {
    "ca_chain": [
      "-----BEGIN CERTIFICATE-----\nMIIDFDCCAfygAwIBAgIUXgxy54mKooz5soqQoRINazH/3pQwDQYJKoZIhvcNAQEL\n...",
      "-----BEGIN CERTIFICATE-----\nMIIDFTCCAf2gAwIBAgIUUo/qwLm5AyqUWqFHw1MlgwUtS/kwDQYJKoZIhvcNAQEL\n..."
    ],
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIDFDCCAfygAwIBAgIUXgxy54mKooz5soqQoRINazH/3pQwDQYJKoZIhvcNAQEL\n...",
    "issuer_id": "7545992c-1910-0898-9e64-d575549fbe9c",
    "issuer_name": "root-x1",
    "key_id": "baadd98d-ec5a-66ac-06b7-dfc91c02c9cf",
    "leaf_not_after_behavior": "truncate",
    "manual_chain": null,
    "usage": "read-only,issuing-certificates,crl-signing,ocsp-signing",
    "revocation_signature_algorithm": "",
    "issuing_certificates": ["<url1>", "<url2>"],
    "crl_distribution_points": ["<url1>", "<url2>"],
    "ocsp_servers": ["<url1>", "<url2>"]
  }
}
```

### Revoke issuer

This endpoint allows an operator to revoke an issuer certificate, marking it
unable to issue new certificates and adding it to other issuers' CRLs, if they
have signed this issuer's certificate. This will cause all CRLs to be rebuilt.

This is mostly provided for book-keeping and as a soft-delete feature, to
ensure this issuer is not accidentally reused in the future.

~> **Warning**: This operation cannot be undone!

~> Note: This operation **does not** have any impact on other clusters or
   mounts and **may not** have any impact on whether clients consider these
   issuers revoked. Revoked issuers will not appear on their own CRLs. Revoked
   issuers may not appear on other CRLs if a suitable parent is not present in
   the same mount point. Revoked issuers will still need to be revoked in any
   other mounts they appear in, both as issuers, in the event of issuer reuse,
   and as issued certificates, in the event of an external parent mount.

| Method  | Path                             |
| :------ | :------------------------------- |
| `POST`  | `/pki/issuer/:issuer_ref/revoke` |

#### Parameters

No parameters.

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    http://127.0.0.1:8200/v1/pki/issuer/old-intermediate/revoke
```

#### Sample response

```text
{
  "data": {
    "ca_chain": [
      "-----BEGIN CERTIFICATE-----\nMIIDFDCCAfygAwIBAgIUXgxy54mKooz5soqQoRINazH/3pQwDQYJKoZIhvcNAQEL\n...",
      "-----BEGIN CERTIFICATE-----\nMIIDFTCCAf2gAwIBAgIUUo/qwLm5AyqUWqFHw1MlgwUtS/kwDQYJKoZIhvcNAQEL\n..."
    ],
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIDFDCCAfygAwIBAgIUXgxy54mKooz5soqQoRINazH/3pQwDQYJKoZIhvcNAQEL\n...",
    "issuer_id": "7545992c-1910-0898-9e64-d575549fbe9c",
    "issuer_name": "old-intermediate",
    "key_id": "baadd98d-ec5a-66ac-06b7-dfc91c02c9cf",
    "leaf_not_after_behavior": "truncate",
    "manual_chain": null,
    "usage": "read-only,issuing-certificates,crl-signing"
    "revocation_time": 1433269787,
  }
}
```

### Delete issuer

This endpoint deletes the specified issuer. A warning is emitted and the
default is cleared if this issuer is the default issuer.

~> **Note**: If an issuer is incorrectly deleted, but its key material
   remains, it is possible to re-import just the issuer certificate. The
   `issuer_id` will change, but the name can be re-assigned to the new
   issuer.

| Method   | Path                      |
| :------- | :------------------------ |
| `DELETE` | `/pki/issuer/:issuer_ref` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request DELETE \
    http://127.0.0.1:8200/v1/pki/issuer/root-x1
```

### Import key

This endpoint allows an operator to import a single pem encoded `rsa`, `ec`, or `ed25519`
key.

~> **Note**: This API does not protect against importing keys using insecure combinations of
  algorithm and key length.

| Method | Path               |
|:-------|:-------------------|
| `POST` | `/pki/keys/import` |

#### Parameters

- `pem_bundle` `(string: <required>)` - Specifies the unencrypted private key in PEM format.

- `key_name` `(string: "")` - Provides a name to the specified key. The
  name must be unique across all keys and not be the reserved value
  `default`.

#### Sample payload

```json
{
  "key_name": "my-imported-key",
  "pem_bundle": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END CERTIFICATE-----"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/keys/import
```

#### Sample response

```text
{
  "data": {
    "key_id": "2cf03991-b052-1dc3-393e-374b41f8dcd8",
    "key_name": "my-imported-key",
    "key_type": "rsa"
  },
}
```

### Read key

This endpoint allows an operator to fetch information about an existing key.

~> **Note**: Vault does not allow reading the value of the private key after
   it has been created.

| Method | Path                |
| :----- | :------------------ |
| `GET`  | `/pki/key/:key_ref` |

#### Parameters

- `key_ref` `(string: <required>)` - Reference to an existing key,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default key, or the name assigned
  to a key. This parameter is part of the request URL.

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/key/default
```

#### Sample response

```text
{
  "data": {
    "key_id": "8c4046f8-52a8-0974-29d2-745d8a0dd848",
    "key_name": "key-root-x1",
    "key_type": "rsa"
  }
}
```

### Update key

This endpoint allows an operator to manage a single key. Currently, the only
parameter that is configurable is the key's name.

Note that it is not possible to change the private key of this key; to
do so, import a new key and a new `key_id` will be assigned.

| Method | Path                |
| :----- | :------------------ |
| `POST` | `/pki/key/:key_ref` |

~> **Note** `POST`ing to this endpoint causes Vault to overwrite the previous
   contents of the key, using the provided request data (and any defaults
   for elided parameters). It does not update only the provided fields.

#### Parameters

- `key_ref` `(string: <required>)` - Reference to an existing key,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default key, or the name assigned
  to a key. This parameter is part of the request URL.

- `key_name` `(string: "")` - Provides a name to the specified key. The
  name must be unique across all keys and not be the reserved value
  `default`.

#### Sample payload

```json
{
  "key_name": "key-root-x1"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/key/default
```

#### Sample response

```text
{
  "data": {
    "key_id": "8c4046f8-52a8-0974-29d2-745d8a0dd848",
    "key_name": "key-root-x1",
    "key_type": "rsa"
  }
}
```

### Delete key

This endpoint deletes the specified key. A warning is emitted and the
default is cleared if this key is the default key.

~> **Note**: Because Vault does not allow exporting the private key
   after it is initially generated, deletion of keys is a sensitive
   operation. Additionally, one key may be used by more than one issuer.
   As a result, Vault prohibits deletion of keys until **all** issuers
   using this key have also been deleted. If these issuers are still
   necessary for chain building, re-import them without the corresponding
   keys after the key has been deleted or use the soft-delete feature
   of issuers.

| Method   | Path                |
| :------- | :------------------ |
| `DELETE` | `/pki/key/:key_ref` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request DELETE \
    http://127.0.0.1:8200/v1/pki/key/key-root-x1
```

### Delete all issuers and keys

This endpoint deletes all issuers and keys within the mount. It is highly
recommended to use the individual delete operations instead. This mount
will be unusable until new issuers and keys are provisioned.

_This endpoint requires sudo/root privileges._

| Method   | Path        |
| :------- | :---------- |
| `DELETE` | `/pki/root` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request DELETE \
    http://127.0.0.1:8200/v1/pki/root
```

---

## Managing authority information

The following privileged endpoints allow the operator to control information
about the core contents of certificates and to perform privileged operations
like rotating the CRLs or performing tidy operations.

### List roles

Refer to the [earlier section](#list-roles) for more information about
listing roles.

### Create/Update role

This endpoint creates or updates the role definition. Note that the
`allowed_domains`, `allow_subdomains`, `allow_glob_domains`, and
`allow_any_name` attributes are additive; between them nearly and across
multiple roles nearly any issuing policy can be accommodated. `server_flag`,
`client_flag`, and `code_signing_flag` are additive as well. If a client
requests a certificate that is not allowed by the CN policy in the role, the
request is denied.

| Method  | Path               |
| :------ | :----------------- |
| `POST`  | `/pki/roles/:name` |
| `PATCH` | `/pki/roles/:name` |

~> **Note** `POST`ing to this endpoint when the role already exists causes
   Vault to overwrite the contents of the role, using the provided request
   data (and any defaults for elided parameters). It does not update only
   the provided fields.<br /><br />
   Since Vault 1.11.0, Vault supports the PATCH operation to this endpoint,
   using the [JSON patch format](https://datatracker.ietf.org/doc/html/rfc6902)
   supported by KVv2, allowing update of specific fields. Note that
   `vault write` uses `POST`.

#### Parameters

- `name` `(string: <required>)` - Specifies the name of the role to create. This
  is part of the request URL.

- `issuer_ref`: `(string: "default")` - Specifies the default issuer of this
  request. May be the value `default`, a name, or an issuer ID. Use ACLs to
  prevent access to the `/pki/issuer/:issuer_ref/{issue,sign}/:name` paths
  to prevent users overriding the role's `issuer_ref` value.

~> Note: This parameter is stored as-is; if the reference is to a name, it
   is **not** resolve to an identifier. Deletion of issuers (or updating their
   names) **may** result in issuance failing or using an unexpected issuer.

~> **Note**: existing roles from previous Vault versions are migrated to use
   the `issuer_ref=default`.

- `ttl` `(string: "")` - Specifies the Time To Live value to be used for the
  validity period of the requested certificate, provided as a string duration
  with time suffix. Hour is the largest suffix. The value specified is strictly
  used for future validity. If not set, uses the system default value or the
  value of `max_ttl`, whichever is shorter. See `not_after` as an alternative
  for setting an absolute end date (rather than a relative one).

- `max_ttl` `(string: "")` - Specifies the maximum Time To Live provided as a
  string duration with time suffix. Hour is the largest suffix. If not set,
  defaults to the system maximum lease TTL.

- `allow_localhost` `(bool: true)` - Specifies if clients can request
  certificates for `localhost` as one of the requested common names. This is
  useful for testing and to allow clients on a single host to talk securely.

~> **Note**: This strictly applies to `localhost` and `localdomain` when this
   option is enabled. Additionally, even if this option is disabled, if either
   name is included in `allowed_domains`, the match rules for that option
   could permit issuance of a certificate for `localhost`.

- `allowed_domains` `(list: [])` - Specifies the domains this role is allowed
  to issue certificates for. This is used with the `allow_bare_domains`,
  `allow_subdomains`, and `allow_glob_domains` options to determine the type
  of matching between these domains and the values of common name, DNS-typed
  SAN entries, and Email-typed SAN entries. When `allow_any_name` is used,
  this attribute has no effect.

~> **Note**: The three options `allow_bare_domains`, `allow_subdomains`, and
   `allow_glob_domains` are each independent of each other. That is, at least
   one type of allowed matching must describe the relationship between the
   `allowed_domains` list and the names on the issued certificate. For example,
   given `allowed_domain=foo.*.example.com` and `allow_subdomains=true` and
   `allow_glob_domains=true`, a request for `bar.foo.baz.example.com` won't
   be permitted, even though it `foo.baz.example.com` matches the glob
   `foo.*.example.com` and `bar` is a subdomain of that.

- `allowed_domains_template` `(bool: false)` - When set, `allowed_domains`
  may contain templates, as with [ACL Path Templating](/vault/docs/concepts/policies).
  Non-templated domains are also still permitted.

- `allow_bare_domains` `(bool: false)` - Specifies if clients can request
  certificates matching the value of the actual domains themselves; e.g. if a
  configured domain set with `allowed_domains` is `example.com`, this allows
  clients to actually request a certificate containing the name `example.com` as
  one of the DNS values on the final certificate. In some scenarios, this can be
  considered a security risk. Note that when an `allowed_domain` field contains
  a potential wildcard character (for example, `allowed_domains=*.example.com`)
  and `allow_bare_domains` and `allow_wildcard_certificates` are both enabled,
  issuance of a wildcard certificate for `*.example.com` will be permitted.

- `allow_subdomains` `(bool: false)` - Specifies if clients can request
  certificates with CNs that are subdomains of the CNs allowed by the other role
  options. _This includes wildcard subdomains._ For example, an
  `allowed_domains` value of `example.com` with this option set to true will
  allow `foo.example.com` and `bar.example.com` as well as `*.example.com`. To
  restrict issuance of wildcards by this option, see `allow_wildcard_certificates`
  below. This option is redundant when using the `allow_any_name` option.

- `allow_glob_domains` `(bool: false)` - Allows names specified in
  `allowed_domains` to contain glob patterns (e.g. `ftp*.example.com`). Clients
  will be allowed to request certificates with names matching the glob
  patterns.

~> **Note**: These globs behave like shell-style globs and can match
  across multiple domain parts. For example, `allowed_domains=*.example.com`
  with `allow_glob_domains` enabled will match not only `foo.example.com` but
  also `baz.bar.foo.example.com`.

~> **Warning**: Glob patterns will match wildcard domains and permit their
   issuance unless otherwise restricted by `allow_wildcard_certificates`. For
   instance, with `allowed_domains=*.*.example.com` and both `allow_glob_domains`
   and `allow_wildcard_certificates` enabled, we will permit the issuance of
   a wildcard certificate for `*.foo.example.com`.

- `allow_wildcard_certificates` `(bool: true)` - Allows the issuance of
  certificates with [RFC 6125](https://tools.ietf.org/html/rfc6125) wildcards
  in the CN field. When set to `false`, this prevents wildcards from being
  issued even if they would've been allowed by an option above. We support
  the following four wildcard types:

  - `*.example.com`, a single wildcard as the entire left-most label,
  - `foo*.example.com`, a single suffixed wildcard in the left-most label,
  - `*foo.example.com`, a single prefixed wildcard in the left-most label, and
  - `f*o.example.com`, a single interior wildcard in the left-most label.

- `allow_any_name` `(bool: false)` - Specifies if clients can request any CN.
  Useful in some circumstances, but make sure you understand whether it is
  appropriate for your installation before enabling it. Note that both
  `enforce_hostnames` and `allow_wildcard_certificates` are still checked,
  which may introduce limitations on issuance with this option.

- `enforce_hostnames` `(bool: true)` - Specifies if only valid host names are
  allowed for CNs, DNS SANs, and the host part of email addresses.

- `allow_ip_sans` `(bool: true)` - Specifies if clients can request IP Subject
  Alternative Names. No authorization checking is performed except to verify
  that the given values are valid IP addresses.

- `allowed_uri_sans` `(string: "")` - Defines allowed URI Subject
  Alternative Names. No authorization checking is performed except to verify
  that the given values are valid URIs. This can be a comma-delimited list or
  a JSON string slice. Values can contain glob patterns (e.g.
  `spiffe://hostname/*`).

- `allowed_uri_sans_template` `(bool: false)` - When set, `allowed_uri_sans`
  may contain templates, as with [ACL Path Templating](/vault/docs/concepts/policies).
  Non-templated domains are also still permitted.

- `allowed_other_sans` `(string: "")` - Defines allowed custom OID/UTF8-string
  SANs. This can be a comma-delimited list or a JSON string slice, where
  each element has the same format as OpenSSL: `<oid>;<type>:<value>`, but
  the only valid type is `UTF8` or `UTF-8`. The `value` part of an element
  may be a `*` to allow any value with that OID.
  Alternatively, specifying a single `*` will allow any `other_sans` input.

- `allowed_serial_numbers` `(string: "")` - If set, an array of allowed serial
  numbers to be requested during certificate issuance. These values support
  shell-style globbing. When empty, custom-specified serial numbers will be
  forbidden. It is strongly recommended to allow Vault to generate random
  serial numbers instead.

- `server_flag` `(bool: true)` - Specifies if certificates are flagged for
  server authentication use. See [RFC 5280 Section 4.2.1.12](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12)
  for information about the Extended Key Usage field.

- `client_flag` `(bool: true)` - Specifies if certificates are flagged for
  client authentication use. See [RFC 5280 Section 4.2.1.12](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12)
  for information about the Extended Key Usage field.

- `code_signing_flag` `(bool: false)` - Specifies if certificates are flagged
  for code signing use. See [RFC 5280 Section 4.2.1.12](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12)
  for information about the Extended Key Usage field.

- `email_protection_flag` `(bool: false)` - Specifies if certificates are
  flagged for email protection use. See [RFC 5280 Section 4.2.1.12](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12)
  for information about the Extended Key Usage field.

- `key_type` `(string: "rsa")` - Specifies the type of key to generate for
  generated private keys and the type of key expected for submitted CSRs.
  Currently, `rsa`, `ec`, and `ed25519` are supported, or when signing
  existing CSRs, `any` can be specified to allow keys of either type
  and with any bit size (subject to >=2048 bits for RSA keys or >= 224 for EC keys).
  When `any` is used, this role cannot generate certificates and can only
  be used to sign CSRs.

~> **Note**: In FIPS 140-2 mode, the following algorithms are not certified
   and thus should not be used: `ed25519`.

- `key_bits` `(int: 0)` - Specifies the number of bits to use for the
  generated keys. Allowed values are 0 (universal default); with
  `key_type=rsa`, allowed values are: 2048 (default), 3072, or
  4096; with `key_type=ec`, allowed values are: 224, 256 (default),
  384, or 521; ignored with `key_type=ed25519` or in signing operations
  when `key_type=any`.

- `signature_bits` `(int: 0)` - Specifies the number of bits to use in
  the signature algorithm; accepts 256 for SHA-2-256, 384 for SHA-2-384,
  and 512 for SHA-2-512. Defaults to 0 to automatically detect based
  on issuer's key length (SHA-2-256 for RSA keys, and matching the curve size
  for NIST P-Curves).

~> **Note**: ECDSA and Ed25519 issuers do not follow configuration of the
   `signature_bits` value; only RSA issuers will change signature types
   based on this parameter.

- `use_pss` `(bool: false)` - Specifies whether or not to use PSS signatures
  over PKCS#1v1.5 signatures when a RSA-type issuer is used. Ignored for
  ECDSA/Ed25519 issuers.

- `key_usage` `(list: ["DigitalSignature", "KeyAgreement", "KeyEncipherment"])` -
  Specifies the allowed key usage constraint on issued certificates. Valid
  values can be found at https://golang.org/pkg/crypto/x509/#KeyUsage - simply
  drop the `KeyUsage` part of the value. Values are not case-sensitive. To
  specify no key usage constraints, set this to an empty list. See
  [RFC 5280 Section 4.2.1.3](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3)
  for more information about the Key Usage field.

- `ext_key_usage` `(list: [])` -
  Specifies the allowed extended key usage constraint on issued certificates. Valid
  values can be found at https://golang.org/pkg/crypto/x509/#ExtKeyUsage - simply
  drop the `ExtKeyUsage` part of the value. Values are not case-sensitive. To
  specify no key usage constraints, set this to an empty list. See
  [RFC 5280 Section 4.2.1.12](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12)
  for information about the Extended Key Usage field.

- `ext_key_usage_oids` `(string: "")` - A comma-separated string or list of extended
  key usage oids. Useful for adding EKUs not supported by the Go standard library.

- `use_csr_common_name` `(bool: true)` - When used with the CSR signing
  endpoint, the common name in the CSR will be used instead of taken from the
  JSON data. This does not include any requested SANs in the CSR; use
  `use_csr_sans` for that.

- `use_csr_sans` `(bool: true)` - When used with the CSR signing endpoint, the
  subject alternate names in the CSR will be used instead of taken from the JSON
  data. This does not include the common name in the CSR; use
  `use_csr_common_name` for that.

- `ou` `(string: "")` - Specifies the OU (OrganizationalUnit) values in the
  subject field of issued certificates. This is a comma-separated string or
  JSON array.

- `organization` `(string: "")` - Specifies the O (Organization) values in the
  subject field of issued certificates. This is a comma-separated string or
  JSON array.

- `country` `(string: "")` - Specifies the C (Country) values in the
  subject field of issued certificates. This is a comma-separated string or
  JSON array.

- `locality` `(string: "")` - Specifies the L (Locality) values in the
  subject field of issued certificates. This is a comma-separated string or
  JSON array.

- `province` `(string: "")` - Specifies the ST (Province) values in the
  subject field of issued certificates. This is a comma-separated string or
  JSON array.

- `street_address` `(string: "")` - Specifies the Street Address values in the
  subject field of issued certificates. This is a comma-separated string or
  JSON array.

- `postal_code` `(string: "")` - Specifies the Postal Code values in the
  subject field of issued certificates. This is a comma-separated string or
  JSON array.

- `generate_lease` `(bool: false)` - Specifies if certificates issued/signed
  against this role will have Vault leases attached to them. Certificates can be
  added to the CRL by `vault revoke <lease_id>` when certificates are associated
  with leases. It can also be done using the `pki/revoke` endpoint. However,
  when lease generation is disabled, invoking `pki/revoke` would be the only way
  to add the certificates to the CRL. When large number of certificates are
  generated with long lifetimes, it is recommended that lease generation be
  disabled, as large amount of leases adversely affect the startup time of Vault.

- `no_store` `(bool: false)` - If set, certificates issued/signed against this
  role will not be stored in the storage backend. This can improve performance
  when issuing large numbers of certificates. However, certificates issued in
  this way cannot be enumerated or revoked via serial number. Certificates may
  still be revoked via [BYOC revocation](#certificate-1).
  This option is recommend only for certificates that are non-sensitive,
  extremely short-lived, or have high volume/turn-over that would prohibit
  storage. This option implies a value of `false` for `generate_lease`.

- `require_cn` `(bool: true)` - If set to false, makes the `common_name` field
  optional while generating a certificate.

- `policy_identifiers` `(list: [])` - A comma-separated string or list of policy
  OIDs.

- `basic_constraints_valid_for_non_ca` `(bool: false)` - Mark Basic Constraints
  valid when issuing non-CA certificates.

- `not_before_duration` `(duration: "30s")` - Specifies the duration by which to
  backdate the NotBefore property. This value has no impact in the validity period
  of the requested certificate, specified in the `ttl` field.

- `not_after` `(string)` - Set the Not After field of the certificate with
  specified date value. The value format should be given in UTC format
  `YYYY-MM-ddTHH:MM:SSZ`. Supports the Y10K end date for IEEE 802.1AR-2018
  standard devices, `9999-12-31T23:59:59Z`.

- `cn_validations` `(list: ["email", "hostname"])` - Validations to run on the
  Common Name field of the certificate. Valid values include:

   - `email`, to ensure the Common Name is an email address (contains an `@` sign),
   - `hostname`, to ensure the Common Name is a hostname (otherwise).

  Multiple values can be separated with a comma or specified as a list and use
  OR semantics (either email or hostname in the CN are allowed). When the
  special value "disabled" is used (must be specified alone), none of the usual
  validation is run (including but not limited to `allowed_domains` and basic
  correctness validation around email addresses and domain names). This allows
  non-standard CNs to be used verbatim from the request.

- `allowed_user_ids` `(string: "")` - Comma separated, globbing list of User ID
  Subject components to allow on requests. By default, no user IDs are allowed.
  Use the bare wildcard `*` value to allow any value. See also the `user_ids`
  request parameter.

#### Sample payload

```json
{
  "allowed_domains": ["example.com"],
  "allow_subdomains": true
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/roles/my-role
```

### Read role

Refer to the [earlier section](#read-role) for more information about
reading roles.

### Delete role

This endpoint deletes the role definition. Deleting a role **does not**
revoke certificates previously issued under this role.

| Method   | Path               |
| :------- | :----------------- |
| `DELETE` | `/pki/roles/:name` |

#### Parameters

- `name` `(string: <required>)` - Specifies the name of the role to delete. This
  is part of the request URL.

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request DELETE \
    http://127.0.0.1:8200/v1/pki/roles/my-role
```

### Read Certificate Issuance External Policy Service (CIEPS) configuration <EnterpriseAlert inline="true" />

This endpoint reads the Certificate Issuance External Policy Service
(CIEPS) engine <EnterpriseAlert inline="true" /> connection properties.

On top of the configuration parameters documented below, this endpoint
returns the following parameters:

 - `external_service_last_updated` - An RFC 3339 timestamp indicating when the
   configuration was last modified.

 - `external_service_validated` - Indicates whether a successful connection to
   the external policy engine has been made under this configuration.

 - `last_successful_request` - Timestamp of the last successful request to
   the external policy engine.

Note that the last two parameters are node-specific and will be reset
whenever the mount reloads (e.g., leadership election or seal/unseal).

| Method | Path                          |
| :----- | :---------------------------- |
| `GET`  | `/pki/config/external-policy` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request GET \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/config/external-policy
```

#### Sample Response

```
{
  "data": {
    "enabled": false,
    "external_service_last_updated": "0001-01-01T00:00:00Z",
    "external_service_url": "",
    "external_service_validated": false,
    "last_successful_request": "",
    "timeout": 15000000000,
    "trusted_ca": "",
    "trusted_leaf_certificate_bundle": "",
    "vault_client_cert_bundle": ""
  },
}

```

### Set Certificate Issuance External Policy Service (CIEPS) configuration <EnterpriseAlert inline="true" />

This endpoint allows enabling the Certificate Issuance External Policy Service
(CIEPS) <EnterpriseAlert inline="true" /> engine and configuring connection
properties.

| Method | Path                          |
| :----- | :---------------------------- |
| `POST` | `/pki/config/external-policy` |

#### Parameters

 - `enabled` `(bool: false)` - Enables or disables the external policy
   service. When disabled, issuance mechanisms under `external-policy`
   paths (e.g., `/pki/external-policy/sign/:policy`) will not work.

 - `external_service_url` `(string: <required>)` - URI to the external
   policy engine. Must use the `https://` scheme.

 - `timeout` `(string: "")` - This is how long any particular API request
   should wait for a timeout at various layers of the stack. Defaults to
   `15s`.

 - `trusted_ca` `(string: "")` - A PEM bundle of trusted CAs to verify the
   certificates presented by the external policy engine against. Optional;
   one of `trusted_ca` or `trusted_leaf_certificate_bundle` must be specified.

 - `trusted_leaf_certificate_bundle` `(string: "")` - A PEM bundle of pinned
   non-CA leaf certificates that must be presented by the external policy
   engine. Optional; one of `trusted_ca` or `trusted_leaf_certificate_bundle`
   must be specified.

 - `vault_client_cert_bundle` `(string: "")` - A PEM bundle of a private key
   and one or more certificates to present during authentication to the
   external policy service.
 - `entity_jmespath` `(string: "")` - A JMESPath expression that will select and filter entity metadata to the service. By default no entity metadata beyond the entity id is sent, use "@" to send all information

 - `group_jmespath` `(string: "")` - A JMESPath expression that will select and filter entity group metadata to the service. By default no group entity metadata is sent, use "@" to send all information
#### Sample payload

```json
{
  "enabled": true,
  "external_service_url": "https://cieps.dadgarcorp.internal",
  "trusted_ca": "-----BEGIN CERTIFICATE-----...."
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/config/external-policy
```

### Read URLs

This endpoint fetches the URLs to be encoded in generated certificates. No URL
configuration will be returned until the configuration is set.

| Method | Path               |
| :----- | :----------------- |
| `GET`  | `/pki/config/urls` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/config/urls
```

#### Sample response

```json
{
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "issuing_certificates": ["<url1>", "<url2>"],
    "crl_distribution_points": ["<url1>", "<url2>"],
    "ocsp_servers": ["<url1>", "<url2>"]
  },
  "auth": null
}
```

### Set URLs

This endpoint allows setting the issuing certificate endpoints, CRL distribution
points, and OCSP server endpoints that will be encoded into issued certificates.
You can update any of the values at any time without affecting the other
existing values. To remove the values, simply use a blank string as the
parameter.

| Method | Path               |
| :----- | :----------------- |
| `POST` | `/pki/config/urls` |

~> **Note**: When using multiple issuers within the same mount, it is strongly
   suggested to use the per-issuer AIA information instead of the global
   AIA information. If any of the per-issuer AIA fields are set, the entire
   issuer's preferences will be used instead. Otherwise, these fields are used
   as a fallback.<br /><br />
   This can be achieved by using _templated_ global AIA values, but setting
   the cluster-local address in configuration. When used, this value **must**
   be set on all performance replication clusters, otherwise issuance will
   fail!

#### Parameters

- `issuing_certificates` `(array<string>: nil)` - Specifies the URL values for
  the Issuing Certificate field. This can be an array or a comma-separated
  string list. See also [RFC 5280 Section 4.2.2.1](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.2.1)
  for information about the Authority Information Access field.

- `crl_distribution_points` `(array<string>: nil)` - Specifies the URL values
  for the CRL Distribution Points field. This can be an array or a
  comma-separated string list. See also [RFC 5280 Section 4.2.1.13](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.13)
  for information about the CRL Distribution Points field.

~> Note: When multiple Performance Replication clusters are enabled, each
   cluster will have its own CRL. Additionally, when multiple issuers are
   in use under a single mount, each issuer will also have its own CRL
   distribution point. These separate CRLs should either be aggregated into a
   single CRL (externally; as Vault does not support this functionality)
   or multiple `crl_distribution_points` should be specified here, pointing
   to each cluster and issuer.

- `ocsp_servers` `(array<string>: nil)` - Specifies the URL values for the OCSP
  Servers field. This can be an array or a comma-separated string list. See also
  [RFC 5280 Section 4.2.2.1](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.2.1)
  for information about the Authority Information Access field.

- `enable_templating` `(bool: false)` - Specifies that the above AIA
  URL values (`issuing_certificates`, `crl_distribution_points`, and
  `ocsp_servers`) should be templated. This replaces the literal value
  `{{issuer_id}}` with the ID of the issuer doing the issuance, the
  literal value `{{cluster_path}}` with the value of `path` from the
  cluster-local configuration endpoint `/config/cluster`, and the
  literal value `{{cluster_aia_path}}` with the value of `aia_path` from
  the cluster-local configuration endpoint `/config/cluster`.

  For example, the following values can be used globally to ensure all AIA
  URIs use the cluster-local, per-issuer canonical reference, but with
  the issuing CA certificate and CRL distribution points to potentially
  use an external, non-Vault CDN.

   - `issuing_certificates={{cluster_aia_path}}/issuer/{{issuer_id}}/der`
   - `crl_distribution_points={{cluster_aia_path}}/issuer/{{issuer_id}}/crl/der`
   - `ocsp_servers={{cluster_aia_path}}/ocsp`

~> **Note**: If no cluster-local address is present and templating is used,
   issuance will fail.

#### Sample payload

```json
{
  "issuing_certificates": ["{{cluster_aia_path}}/issuer/{{issuer_id}}/der"],
  "crl_distribution_points": ["{{cluster_aia_path}}/issuer/{{issuer_id}}/crl/der"],
  "ocsp_servers": ["{{cluster_aia_path}}/ocsp"]
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/config/urls
```

### Read issuers configuration

This endpoint allows getting the value of the default issuer.

| Method | Path                  |
| :----- | :-------------------- |
| `GET`  | `/pki/config/issuers` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/config/issuers
```

#### Sample response

```json
{
  "data": {
    "default": "3dc79a5a-7a6c-70e2-1123-94b88557ba12",
    "default_follows_latest_issuer": "false"
  }
}
```

### Set issuers configuration

This endpoint allows setting the value of the default issuer.

| Method | Path                  |
| :----- | :-------------------- |
| `POST` | `/pki/config/issuers` |
| `POST` | `/pki/root/replace`   |

#### Parameters

- `default` `(string: "")` - Specifies the default issuer (by reference;
  either a name or an ID). When no value is specified and the path is
  `/pki/root/replace`, the default value of `"next"` will be used.

- `default_follows_latest_issuer` `(bool: false)` - Specifies whether a
  root creation or an issuer import operation updates the default issuer
  to the newly added issuer.

  While the new multi-issuer functionality of 1.11 was backwards compatible
  on a per-API basis, some applications relied explicitly on unsafe behavior
  across multiple APIs that we addressed. For instance, calling
  `/intermediate/generate/:type` would silently remove any (potentially
  in-use!) key material and generate new private keys. While our response to
  this endpoint is backwards compatible (returning a new key and safely
  preserving old keys), some applications implicitly relied on this behavior.
  This new option is meant to provide compatibility across API calls to these
  callers: the newly created issuer (once _imported_ -- not on intermediate
  generation) will become the default and it will look (to anyone strictly
  using old APIs) that it is the only issuer in the mount. However, it is
  encouraged for applications to update to the newer, safer semantics
  associated with [multi-issuer rotation](/vault/docs/secrets/pki/rotation-primitives).

~> Note: When an import creates more than one new issuer with key material
   known to this mount, no default update will occur.

#### Sample payload

```json
{
  "default": "root-x1"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/config/issuers
```

#### Sample response

```json
{
  "data": {
    "default": "3dc79a5a-7a6c-70e2-1123-94b88557ba12"
  }
}
```

### Read keys configuration

This endpoint allows getting the value of the default key.

| Method | Path               |
| :----- | :----------------- |
| `GET`  | `/pki/config/keys` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/config/keys
```

#### Sample response

```json
{
  "data": {
    "default": "baadd98d-ec5a-66ac-06b7-dfc91c02c9cf"
  }
}
```

### Set keys configuration

This endpoint allows setting the value of the default key.

| Method | Path               |
| :----- | :----------------- |
| `POST` | `/pki/config/keys` |

#### Parameters

- `default` `(string: "")` - Specifies the default key (by reference;
  either a name or an ID).

#### Sample payload

```json
{
  "default": "baadd98d-ec5a-66ac-06b7-dfc91c02c9cf"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/config/keys
```

#### Sample response

```json
{
  "data": {
    "default": "baadd98d-ec5a-66ac-06b7-dfc91c02c9cf"
  }
}
```

### Read cluster configuration

This endpoint fetches the cluster-local configuration.

The cluster-local config has `path`, which sets the URL to this mount on
a particular performance replication cluster. This is useful for populating
`{{cluster_path}}` during AIA URL templating, but may be used for other
values in the future.

It also has `aia_path`, which allows using a non-Vault, external responder,
setting the `{{cluster_aia_path}}` value for AIA URL templating. This is
useful for distributing CA and CRL information over an unsecured, non-TLS
channel.

| Method | Path                  |
| :----- | :-------------------- |
| `GET`  | `/pki/config/cluster` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/config/cluster
```

#### Sample response

```json
{
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "path": "<url>",
    "aia_path": "<url>"
  },
  "auth": null
}
```

### Set cluster configuration

This endpoint sets cluster-local configuration.

The cluster-local config has `path`, which sets the URL to this mount on
a particular performance replication cluster. This is useful for populating
`{{cluster_path}}` during AIA URL templating, but may be used for other
values in the future.

It also has `aia_path`, which allows using a non-Vault, external responder,
setting the `{{cluster_aia_path}}` value for AIA URL templating. This is
useful for distributing CA and CRL information over an unsecured, non-TLS
channel.

| Method | Path                  |
| :----- | :-------------------- |
| `POST` | `/pki/config/cluster` |

#### Parameters

- `path` `(string: "")` - Specifies the path to this performance replication
  cluster's API mount path, including any namespaces as path components.
  For example, `https://pr-a.vault.example.com/v1/ns1/pki-root`.

- `aia_path` `(string: "")` - Specifies the path to this performance replication
  cluster's AIA distribution point; may refer to an external, non-Vault responder.
  This is for resolving AIA URLs and providing the `{{cluster_aia_path}}` template
  parameter and will not be used for other purposes. As such, unlike `path` above,
  this could safely be an insecure transit mechanism (like HTTP without TLS).

#### Sample payload

```json
{
  "path": "https://...",
  "aia_path": "http://..."
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/config/cluster
```

### Read CRL configuration

This endpoint allows getting the duration for which the generated CRL should be
marked valid. No CRL configuration will be returned until the configuration is
set, but the CRL will still default to enabled with 72h expiration.

| Method | Path              |
| :----- | :---------------- |
| `GET`  | `/pki/config/crl` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/config/crl
```

#### Sample response

```json
{
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "disable": false,
    "expiry": "72h",
    "ocsp_disable": false,
    "ocsp_expiry": "12h",
    "auto_rebuild": false,
    "auto_rebuild_grace_period": "12h",
    "enable_delta": false,
    "delta_rebuild_interval": "15m",
    "cross_cluster_revocation": true,
    "unified_crl": true,
    "unified_crl_on_existing_paths": true
  },
  "auth": null
}
```

<a name="set-crl-configuration"></a>

### Set revocation configuration

This endpoint allows setting the duration for which the generated CRL should be
marked valid. If the CRL is disabled, it will return a signed but zero-length
CRL for any request. If enabled, it will re-build the CRL.

If the `ocsp_disable` key is set to `true`, the OCSP responder will always
respond with an Unauthorized OCSP response to any request.

~> **Note**: This parameter is global, across all clusters and issuers. Use
   the per-issuer `usage` field to disable CRL building for a specific
   issuer, while leaving the global CRL building enabled.

~> Note: Disabling the CRL does not affect whether revoked certificates are
stored internally. Certificates that have been revoked when a role's
certificate storage is enabled will continue to be marked and stored as
revoked until `tidy` has been run with the desired safety buffer. Re-enabling
CRL generation will then result in all such certificates becoming a part of
the CRL.

~> Note: Enabling automatic rebuilding of CRLs disables immediate regeneration
   on revocation. This is in line with the behavior of other CAs which only
   rebuild CRLs periodically. We suggest manually hitting the rotate if a
   fresh CRL is necessary after a revocation. For the most part though, CRLs
   should not be relied upon for the latest certificate status information,
   and OCSP should be used instead.

~> Note: The periodic function which controls automatic rebuilding of CRLs
   and delta CRLs only executes once a minute; this prevents high system load
   but limits the granularity of the temporal options below.

~> Note: The `unified_crl`, `unified_crl_on_existing_paths`, and
   `cross_cluster_revocation` parameters are all Vault Enterprise only
   functionality. While they appear in the responses on Vault Community Edition, they cannot
   be enabled.

| Method | Path              |
| :----- | :---------------- |
| `POST` | `/pki/config/crl` |

#### Parameters

- `expiry` `(string: "72h")` - The amount of time the generated CRL should be valid.

- `disable` `(bool: false)` - Disables or enables CRL building.

- `ocsp_disable` `(bool: false)` - Disables or enables the OCSP responder in Vault.

- `ocsp_expiry` `(string: "12h")` - The amount of time an OCSP response can be cached for,
  (controls the NextUpdate field), useful for OCSP stapling refresh durations. Setting to 0
  should effectively disable caching in third party systems.

- `auto_rebuild` `(bool: false)` - Enables or disables periodic rebuilding of
  the CRL upon expiry.

- `auto_rebuild_grace_period` `(string: "12h")` - Grace period before CRL expiry
  to attempt rebuild of CRL. Must be shorter than the CRL expiry period.

- `enable_delta` `(bool: false)` - Enables or disables building of delta CRLs
  with up-to-date revocation information, augmenting the last complete CRL.
  This option requires `auto_rebuild` to also be enabled.

- `delta_rebuild_interval` `(string: "15m")` - Interval to check for new
  revocations on, to regenerate the delta CRL. Must be shorter than CRL
  expiry.

- `cross_cluster_revocation` `(bool: false)` -
  <EnterpriseAlert product="vault" inline /> Enables cross-cluster revocation
  request queues. When a serial not issued on this local cluster is presented
  to Vault via the [`/revoke` API](#revoke-certificate), it is replicated
  across clusters and the cluster which issued that certificate will revoke
  it if it is online.

~> Note: API calls to revoke a certificate with Bring Your Own Certificate
   (BYOC) will always trigger a local revocation of that certificate. No
   cross-cluster revocation request will be created.<br /><br />
   API calls to revoke a certificate with Proof of Possession (PoP) cannot
   be satisfied if the certificate is not available locally and will
   not result in a cross-cluster revocation request.

- `unified_crl` `(bool: false)` -
  <EnterpriseAlert product="vault" inline /> Enables unified CRL and OCSP building. This
  synchronizes all revocations between clusters; a single, unified CRL will be
  built on the active node of the primary performance replication (PR)
  cluster. Any node in any PR cluster will be able to serve this unified CRL
  and respond to unified OCSP inquiries.

~> Note: This option ensures existing, non-expired revocations are
   consistently reported. If a certificate was issued and stored on one
   cluster, but revoked via BYOC on another, this option will inform the
   issuing cluster of the revocation.

- `unified_crl_on_existing_paths` `(bool: false)` -
  <EnterpriseAlert product="vault" inline /> Enables serving the
  unified CRL and OCSP on the existing, previously cluster-local paths
  (e.g., `/pki/crl` will now contain the unified CRL when enabled). This
  allows transitioning AIA-based consumption of CRLs to a unified view
  without having to re-issue certificates or update scripts pulling
  a single CRL.

#### Sample payload

```json
{
  "expiry": "48h",
  "disable": "false",
  "ocsp_disable": "false",
  "ocsp_expiry": "12h",
  "auto_rebuild": "true",
  "auto_rebuild_grace_period": "8h",
  "enable_delta": "true",
  "delta_rebuild_interval": "10m",
  "cross_cluster_revocation": true,
  "unified_crl": true,
  "unified_crl_on_existing_paths": true,
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/config/crl
```

### Rotate CRLs

This endpoint forces a rotation of all issuers' CRLs. This can be used by
administrators to cut the size of the CRL if it contains a number of
certificates that have now expired, but has not been rotated due to no further
certificates being revoked. If no certificates have been revoked, but the CRL
has expired or is close to expiring, administrators **must** hit this endpoint
to manually rotate the CRL. This rotates all CRLs on the present cluster,
and **must** be called on every cluster.

~> **Note**: Mirroring the behavior of earlier Vault versions, we add
   certificates revoked by an unknown issuer to the default issuer's CRL.
   To fully purge old revoked, unexpired certificates, it is not sufficient
   to delete their issuer and is instead necessary to **remove** the mount
   completely.

~> **Note**: As of Vault 1.12, it is suggested to switch to enabling the CRL's
   `auto_rebuild` functionality to avoid having to manually hit the Rotate
   endpoint when the CRL expires. This ensures a valid CRL is always
   maintained, at the expense of potentially not being up-to-date. If a
   revocation occurs that must be immediately propagated, this endpoint can
   be used to regenerate the CRL, though distribution must still occur outside
   of Vault (either manually or via AIA where supported).

| Method | Path              |
| :----- | :---------------- |
| `GET`  | `/pki/crl/rotate` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/crl/rotate
```

#### Sample response

```json
{
  "data": {
    "success": true
  }
}
```

### Rotate delta CRLs

This endpoint forces a rotation of all issuers' delta CRLs, when enabled.
This can be used by administrators to force a rebuild of a delta CRL if
high-profile revocations have occurred and there's a long high interval
between delta rebuilds (`delta_rebuild_interval`).

See notes about rotating regular CRLs above as they apply here as well.

| Method | Path                    |
| :----- | :---------------------- |
| `GET`  | `/pki/crl/rotate-delta` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/crl/rotate
```

#### Sample response

```json
{
  "data": {
    "success": true
  }
}
```

### Combine CRLs from the same issuer

This endpoint allows combining multiple different CRLs that have been signed by the
same issuer into a single signed CRL. This is useful to generate a single authoritative
CRL of revocations across distinct Vault clusters such as primary and performance replica
clusters.


| Method | Path                                  |
|:-------|:--------------------------------------|
| `POST` | `/pki/issuer/:issuer_ref/resign-crls` |


#### Parameters

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.
- `crls` `(list of strings: <required>)` - A list of PEM encoded CRLs that have been
  signed by the issuer
- `crl_number` `(int: <required>)` - The sequence number to be written within the CRL
  Number extension.
- `delta_crl_base_number` `(int: -1)` - Using a value of 0 or greater specifies the base CRL revision
  number to encode within a Delta CRL indicator extension, otherwise the extension will
  not be added; defaults to -1.
- `format` `(string: pem)` - The format of the combined CRL, can be "pem" or "der".
  If "der", the value will be base64 encoded; Defaults to "pem".
- `next_update` `(string: 72h)` - The amount of time the generated CRL should be
  valid; defaults to 72 hours.

#### Sample payload

```json
{
  "crl_number": "10",
  "next_update": "24h",
  "crls": ["<PEM crl 1>", "<PEM crl 2>"],
  "format": "pem"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    -request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/issuer/default/resign-crls
```

#### Sample response

```json
{
  "data": {
    "crl": "<PEM encoded crl>"
  }
}
```

### Sign revocation list

This endpoint allows generating a CRL based on the provided parameter data from any external
source and signed by the specified issuer. Values are taken verbatim from the parameters provided.

**This is a potentially dangerous endpoint and only highly trusted users should have access.**

| Method | Path                                           |
|:-------|:-----------------------------------------------|
| `POST` | `/pki/issuer/:issuer_ref/sign-revocation-list` |


#### Parameters

- `issuer_ref` `(string: <required>)` - Reference to an existing issuer,
  either by Vault-generated identifier, the literal string `default` to
  refer to the currently configured default issuer, or the name assigned
  to an issuer. This parameter is part of the request URL.
- `crl_number` `(int: <required>)` - The sequence number to be written within the CRL
  Number extension.
- `delta_crl_base_number` `(int: -1)` - Using a value of 0 or greater specifies the base CRL revision
  number to encode within a Delta CRL indicator extension, otherwise the extension will
  not be added; defaults to -1.
- `format` `(string: pem)` - The format of the combined CRL, can be "pem" or "der".
  If "der", the value will be base64 encoded; Defaults to "pem".
- `next_update` `(string: 72h)` - The amount of time the generated CRL should be
  valid; defaults to 72 hours.
- `revoked_certs` `(type: slice of maps)` - Each element contains revocation information for a
  single serial number along with the revocation time and the serial's extensions if any. Each
  element can have the following key/values
   - `serial_number` `(type: string)` - the serial number of the revoked cert
   - `revocation_time` `(type: string)` - the revocation time, unix int format or RFC3339 encoding supported
   - `extensions` `(type: slice of maps)` - A slice of all extensions that should be added to the revoked
      certificate entry. Each ele,ent contains a map with the following entries
     - `id` `(type: string)` - an ASN1 object identifier in dot notation
     - `critical` `(type: bool)` - should the extension be marked critical
     - `value` `(type: string)` - base64 encoded bytes for extension value
- `extensions` `(type: slice of maps)` - A slice of all extensions that should be added to the generated
  CRL each element containing a map with the following entries.
   - `id` `(type: string)` - an ASN1 object identifier in dot notation
   - `critical` `(type: bool)` - should the extension be marked critical
   - `value` `(type: string)` - base64 encoded bytes for extension value

~> **Note**:: The following extension ids are not allowed to be provided and can be influenced by other parameters
  - `2.5.29.20`: CRL Number
  - `2.5.29.27`: Delta CRL
  - `2.5.29.35`: Authority Key Identifier

#### Sample payload

```json
{
  "crl_number": "10",
  "next_update": "24h",
  "format": "pem",
  "revoked_certs": [
    {
      "serial_number": "39:dd:2e:90:b7:23:1f:8d:d3:7d:31:c5:1b:da:84:d0:5b:65:31:58",
      "revocation_time": "2009-11-10T23:00:00Z"
    },
    {
      "serial_number": "40:33:2e:90:b7:23:1f:8d:d3:7d:31:c5:1b:da:84:d0:5b:65:31:58",
      "revocation_time": "1257894000"
    }
  ]
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    -request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/issuer/default/sign-revocation-list
```

#### Sample response

```json
{
  "data": {
    "crl": "<PEM encoded crl>"
  }
}
```

### Tidy

This endpoint allows tidying up the storage backend and/or CRL by removing
certificates that have expired and are past a certain buffer period beyond their
expiration time.

| Method | Path        |
| :----- | :---------- |
| `POST` | `/pki/tidy` |

~> Note: it is encouraged to use the [automatic tidy capabilities](#configure-automatic-tidy)
   to ensure this gets run periodically.

#### Parameters

- `tidy_cert_store` `(bool: false)` - Specifies whether to tidy up the certificate
  store.

- `tidy_revoked_certs` `(bool: false)` - Set to true to remove all invalid and
  expired certificates from storage. A revoked storage entry is considered
  invalid if the entry is empty, or the value within the entry is empty. If a
  certificate is removed due to expiry, the entry will also be removed from the
  CRL, and the CRL will be rotated.

- `tidy_revoked_cert_issuer_associations` `(bool: false)` - Set to true to associate
  revoked certificates with their corresponding issuers; this improves the
  performance of OCSP and CRL building, by shifting work to a tidy operation
  instead.

~> Note: With multiple issuers, a CA which issued a particular revoked
   certificate may be removed and re-added, resulting in a different issuer
   ID value. When building CRLs, these links are automatically updated for any
   missing or added issuers, but during OCSP this value is computed and then
   discarded, potentially causing a performance penalty on each request.
   During regular CA operations, it is not necessary to run this operation.
   <br /><br />
   It is suggested to run this tidy when removing or importing new issuers and
   on the first upgrade to a post-1.11 Vault version, but otherwise not to run
   it during automatic tidy operations.

- `tidy_expired_issuers` `(bool: false)` - Set to true to automatically remove
  expired issuers after the `issuer_safety_buffer` duration has elapsed. We
  log the issuer certificate on removal to allow recovery; no keys are removed
  during this process.

~> Note: The default issuer will not be removed even if it has expired and is
   past the `issuer_safety_buffer` specified.

- `tidy_move_legacy_ca_bundle` `(bool: false)` - Set to true to backup any
  legacy CA/issuers bundle (from Vault versions earlier than 1.11) to
  `config/ca_bundle.bak`. This can be restored with `sys/raw` back to
  `config/ca_bundle` if necessary, but won't impact mount startup (as
  mounts will attempt to read the latter and do a migration of CA issuers
  if present). Migration will only occur after `issuer_safety_buffer` has
  passed since the last successful migration.

- `tidy_revocation_queue` `(bool: false)` - Set to true to remove stale
  revocation request entries that haven't been confirmed by any active
  node of a performance replication (PR) cluster. Only runs on the active
  node of the primary cluster.

~> Note: this tidy is only applicable on Vault Enterprise.

- `tidy_cross_cluster_revoked_certs` `(bool: false)` - Set to true to remove
  expired, cross-cluster revocation entries. This is the cross-cluster
  equivalent of `tidy_revoked_certs`. Only runs on the active node of the
  primary cluster.

~> Note: this tidy is only applicable on Vault Enterprise.

- `safety_buffer` `(string: "")` - Specifies a duration using [duration format strings](/vault/docs/concepts/duration-format)
  used as a safety buffer to ensure certificates are not expunged prematurely; as an example, this can keep
  certificates from being removed from the CRL that, due to clock skew, might
  still be considered valid on other hosts. For a certificate to be expunged,
  the time must be after the expiration time of the certificate (according to
  the local clock) plus the duration of `safety_buffer`. Defaults to `72h`.

- `issuer_safety_buffer` `(string: "")` - Specifies a duration that issuers
  should be kept for, past their `NotAfter` validity period. Defaults to
  365 days as hours (`8760h`).

- `pause_duration` `(string: "0s")` - Specifies the duration to pause
  between tidying individual certificates. This releases the revocation
  lock and allows other operations to continue while tidy is paused.
  This allows an operator to control tidy's resource utilization within
  a timespan: the LIST operation will remain in memory, but the space
  between reading, parsing, and updates on-disk cert entries will be
  increased, decreasing resource utilization.

  Does not affect `tidy_expired_issuers`.

~> Note: Using too long of a `pause_duration` can result in tidy operations
   not concluding during this lifetime! Using too short of a pause duration
   (but non-zero) can lead to lock contention. Use [tidy's cancellation](#cancel-tidy)
   to stop a running operation after the sleep period is over.

- `revocation_queue_safety_buffer` `(string: "")` - Specifies a duration
  after which cross-cluster revocation requests will be removed as expired.
  This should be set high enough that, if a cluster disappears for a while
  but later comes back, any revocation requests which it should process will
  still be there, but not too long as to fill up storage with too many invalid
  requests. Defaults to `48h`.

 - `tidy_acme` `(bool: false)` - Set to true to tidy stale ACME accounts,
   orders, authorizations, EABs, and challenges. ACME orders are tidied (deleted)
   `safety_buffer` after the certificate associated with them expires, or after
   the order and relevant authorizations have expired if no certificate was
   produced. Authorizations are tidied with the corresponding order.

   When a valid ACME Account is at least `acme_account_safety_buffer`
   old, and has no remaining orders associated with it, the account is
   marked as revoked. After another `acme_account_safety_buffer` has
   passed from the revocation or deactivation date, a revoked or
   deactivated ACME account is deleted.

 - `acme_account_safety_buffer` `(string: "720h")` - The amount of time that
   must pass after creation that an account with no orders is marked revoked,
   and the amount of time after being marked revoked or deactivated. The
   default is 30 days as hours.

#### Sample payload

```json
{
  "safety_buffer": "24h"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/tidy
```

### Read automatic tidy configuration

This endpoint fetches the current automatic tidy configuration.

This is the combination of the periodic invocation parameters described
[in the below write handler](#set-automatic-tidy-configuration) and
the tidy parameters [described above in the tidy endpoint](#tidy).

| Method | Path                    |
| :----- | :---------------------- |
| `GET`  | `/pki/config/auto-tidy` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/config/auto-tidy
```

#### Sample response

```json
{
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "enabled": false,
    "interval_duration": 43200,
    "issuer_safety_buffer": 31536000,
    "maintain_stored_certificate_counts": false,
    "pause_duration": "0s",
    "publish_stored_certificate_count_metrics": false,
    "revocation_queue_safety_buffer": 172800,
    "safety_buffer": 259200,
    "tidy_cert_store": false,
    "tidy_cross_cluster_revoked_certs": false,
    "tidy_expired_issuers": false,
    "tidy_move_legacy_ca_bundle": false,
    "tidy_revocation_queue": false,
    "tidy_revoked_cert_issuer_associations": false,
    "tidy_revoked_certs": false
  },
  "auth": null
}
```

<a name="configure-automatic-tidy"></a>

### Set automatic tidy configuration

This endpoint allows configuring periodic tidy operations, using the tidy mechanism
described above. Status is from automatically run tidies are still reported at the
status endpoint described below.

| Method | Path                    |
| :----- | :---------------------- |
| `POST` | `/pki/config/auto-tidy` |

#### Parameters

The below parameters are in addition to the regular parameters accepted by the
[`/pki/tidy` endpoint](#tidy) documented above.

- `enabled` `(bool: false)` - Specifies whether automatic tidy is enabled or not.

- `interval_duration` `(string: "")` - Specifies the duration between automatic tidy
  operations; note that this is from the end of one operation to the start of
  the next so the time of the operation itself does not need to be considered.
  Defaults to 12h

- `maintain_stored_certificate_counts` `(bool: false)` - When enabled,
  maintains expensive counts of certificates. During initialization of the
  mount, a LIST of all certificates is performed to get a baseline figure and
  throughout operations like issuance, revocation, and subsequent tidies, the
  figure is updated.

~> *Note*: It is strongly recommend to not enable this value if 50k or more
   certificates are stored in the mount or if many PKI mounts are in use in
   this cluster. Instead, use audit logs and aggregate this data externally
   to Vault so as not to impact Vault performance.

- `publish_stored_certificate_count_metrics` `(bool: false)` - When enabled,
  publishes the value computed by `maintain_stored_certificate_counts` to
  the mount's metrics. This requires the former to be enabled.

#### Sample payload

```json
{
  "enabled": true,
  "tidy_revoked_cert_issuer_associations": true,
  "safety_buffer": "24h"
}
```

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/pki/config/auto-tidy
```

### Tidy status

This is a read only endpoint that returns information about the current tidy
operation, or the most recent if none are currently running.

The result includes the following fields:

* `safety_buffer`: the value of this parameter when initiating the tidy operation
* `tidy_cert_store`: the value of this parameter when initiating the tidy operation
* `tidy_revoked_certs`: the value of this parameter when initiating the tidy operation
* `state`: one of *Inactive*, *Running*, *Finished*, *Error*, *Cancelling*, or *Cancelled*
* `error`: the error message, if the operation ran into an error
* `time_started`: the time the operation started
* `time_finished`: the time the operation finished
* `message`: One of *Tidying certificate store: checking entry N of TOTAL* or
  *Tidying revoked certificates: checking certificate N of TOTAL*
* `cert_store_deleted_count`: The number of certificate storage entries deleted
* `revoked_cert_deleted_count`: The number of revoked certificate entries deleted
* `missing_issuer_cert_count`: The number of revoked certificates which were missing a valid issuer reference
* `tidy_expired_issuers`: the value of this parameter when initiating the tidy operation
* `issuer_safety_buffer`: the value of this parameter when initiating the tidy operation
* `tidy_move_legacy_ca_bundle`: the value of this parameter when initiating the tidy operation
* `tidy_revocation_queue`: the value of this parameter when initiating the tidy operation
* `revocation_queue_deleted_count`: the number of revocation queue entries deleted
* `tidy_cross_cluster_revoked_certs`: the value of this parameter when initiating the tidy operation
* `cross_revoked_cert_deleted_count`: the number of cross-cluster revoked certificate entries deleted
* `revocation_queue_safety_buffer`: the value of this parameter when initiating the tidy operation
* `pause_duration`: the value of this parameter when initiating the tidy operation
* `last_auto_tidy_finished`: the time when the last auto-tidy operation finished; may be different than `time_finished` especially if the last operation was a manually executed tidy operation. Set to current time at mount time to delay the initial auto-tidy operation; not persisted.


| Method | Path               |
| :----- | :----------------- |
| `GET`  | `/pki/tidy-status` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request GET \
    http://127.0.0.1:8200/v1/pki/tidy-status

```

#### Sample response

```json
  "data": {
    "safety_buffer": 60,
    "tidy_cert_store": true,
    "tidy_revoked_certs": true,
    "error": null,
    "message": "Tidying certificate store: checking entry 234 of 488",
    "revoked_cert_deleted_count": 0,
    "cert_store_deleted_count": 2,
    "state": "Running",
    "time_started": "2021-10-20T14:52:13.510161-04:00",
    "time_finished": null
  },
```

### Cancel tidy

This endpoint allows cancelling a running tidy operation. It takes no
parameter and cancels the tidy at the next available checkpoint, which
may process additional certificates between when the operation was
marked as cancelled and when the operation stopped.

The response to this endpoint is the same as the [status](#tidy-status).

| Method | Path               |
| :----- | :----------------- |
| `POST` | `/pki/tidy-cancel` |

#### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    http://127.0.0.1:8200/v1/pki/tidy-cancel

```

#### Sample response

```json
  "data": {
    "safety_buffer": 60,
    "tidy_cert_store": true,
    "tidy_revoked_certs": true,
    "error": null,
    "message": "Tidying certificate store: checking entry 234 of 488",
    "revoked_cert_deleted_count": 0,
    "cert_store_deleted_count": 2,
    "state": "Cancelling",
    "time_started": "2021-10-20T14:52:13.510161-04:00",
    "time_finished": null
  },
```

---

## Cluster scalability

See [PKI Cluster Scalability](/vault/docs/secrets/pki/considerations#cluster-scalability) in the considerations page.

## Managed keys

~> Note: Managed keys are an Enterprise only feature.

The [Generate Root](#generate-root) and [Generate Intermediate](#generate-intermediate)
API calls can leverage the Managed Keys feature, delegating operations that
require private key material to an external system.

To leverage a Managed Key, assuming it has already been configured, set the type
parameter to `kms` within either, [Generate Root](#generate-root) or
[Generate Intermediate](#generate-intermediate) APIs, and one of either
`managed_key_name` or `managed_key_id` parameters specifying a Managed Key to use.
As with the `internal` type for those APIs, if the type parameter is set to `kms`,
there is no way to read/fetch the private key.

The API call will fail if the specified Managed Key is not properly configured or
arguments detailing private key attributes are specified such as `key_type` or
`key_bits`.

Once either of the certificate APIs have successfully executed, all other PKI
operations behave the same, with no other special configuration or parameters required.


## Vault CLI with DER/PEM responses

The Vault CLI can only display JSON responses. For APIs that return non-JSON formatted
data such as DER and PEM formats, `vault read` will fail without the `-format=raw`
option added in Vault 1.13 or another client such as `curl` must be used.
